<?php

namespace App\V3\V3_2_7\Services;

use App\Services\CommonService;
use App\V3\V3_2_7\Models\AdminAddendumModel;
use App\V3\V3_2_7\Models\AdminModel;
use App\V3\V3_2_7\Models\ApplicationGoodsModel;
use App\V3\V3_2_7\Models\LocationLogModel;
use App\V3\V3_2_7\Models\LogInStorageModel;
use App\V3\V3_2_7\Models\LogOutPackageModel;
use App\V3\V3_2_7\Models\LogOutStorageModel;
use App\V3\V3_2_7\Models\LogPackageContentModel;
use App\V3\V3_2_7\Models\LogPackageModel;
use App\V3\V3_2_7\Models\MaterielAnimalInfoModel;
use App\V3\V3_2_7\Models\MaterielClassModel;
use App\V3\V3_2_7\Models\MaterielModel;
use App\V3\V3_2_7\Models\MaterielProductContentModel;
use App\V3\V3_2_7\Models\MaterielsTypeModel;
use App\V3\V3_2_7\Models\MaterielTypeModel;
use App\V3\V3_2_7\Models\OperMainAccountModel;
use App\V3\V3_2_7\Models\OverflowBreakageModel;
use App\V3\V3_2_7\Models\PackageContentModel;
use App\V3\V3_2_7\Models\ProductOrderModel;
use App\V3\V3_2_7\Models\SalesReturnModel;
use App\V3\V3_2_7\Models\SellGoodsDetailBatchModel;
use App\V3\V3_2_7\Models\SellGoodsDetailModel;
use App\V3\V3_2_7\Models\SellMaterielPrepareOutLogModel;
use App\V3\V3_2_7\Models\SellModel;
use App\V3\V3_2_7\Models\SellPackageContentModel;
use App\V3\V3_2_7\Models\SellPackageDetailModel;
use App\V3\V3_2_7\Models\SerialNumberModel;
use App\V3\V3_2_7\Models\StorageBatchModel;
use App\V3\V3_2_7\Models\StorageManageModel;
use App\V3\V3_2_7\Models\StorageModel;
use App\V3\V3_2_7\Models\StorageShelfLocationModel;
use App\V3\V3_2_7\Models\StorageShelfModel;
use App\V3\V3_2_7\Models\CheckModel;
use App\V3\V3_2_7\Models\SellGoodsDetail;
use App\Services\MessageService;
use App\V3\V3_2_7\Models\TallyModel;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use App\V3\V3_2_7\Models\SellGoodsListModel;
use App\V3\V3_2_7\Models\SellOutSerialNumbersModel;
use App\V3\V3_2_7\Models\PackageComponentWarehouseLogModel;
use Illuminate\Support\Carbon;
use App\V3\V3_2_7\Models\DelSerialNumberModel;
use Milon\Barcode\DNS1D;

class StorageManageService
{
    static public function readGoodsIdInfo($data)
    {
        //查询是否是组件的id，如果是返回组件套餐id
        $info = MaterielTypeModel::where('id', $data['goods_id'])
            ->where('delete_flag', 0)
            ->first()->toArray();

        if (!empty($info['id'])) {
            return $info;
        } else {
            return "";
        }
    }

    static public function checkMatierlInStorageOrNot($id, $mainId)
    {
        $info = StorageManageModel::where([
            'type_id' => $id,
            'main_id' => $mainId,
            'delete_flag' => 0
        ])->where('in_storage_num', '!=', 0)->first();

        if (!empty($info)) {
            return false;
        } else {
            return true;
        }
    }

    //删除库存信息
    static public function del($data)
    {
        $data['model_type'] = $data['model_type'] ?? 1;
        $logData = '';
        $list = StorageManageModel::query()
            ->where('main_id', $data['main_id'])
            ->where(function ($query) use ($data) {
                if ($data['model_type'] == 1) {
                    $query->where('storage_id', $data['id']);
                } else {
                    $query->where('id', $data['id']);
                }
            })->get();


        foreach ($list as $val) {
            /*if($val['in_storage_num'] > 0) {
                return ['code' => 1, 'msg' => '当商品库存数为0时才可删除，当前库存数为：'.$val['in_storage_num'], 'data' => ''];
            } */
            $val->delete_flag = 1;
            $val->save();
            $logData .= '商品名称：' . $val['materiel_name'] . '（' . $val['materiel_no'] . '）' .
                ' 对应的仓库：' . $val['storage_name'] . ' 库存信息已删除！';
        }

        CommonService::log('删除库存信息', $data, $logData);
        return ['code' => 0, 'msg' => '删除成功', 'data' => ''];
    }

    //库存查看列表
    public static function materielStorageList($id)
    {
        $id = array_filter(explode(',', $id), function ($v) {
            return $v !== '';
        });

        $storageManageInfo = StorageManageModel::query()->select(
            'a.id as storage_manage_id',
            'a.type_id',
            'a.storage_id',
            'b.materiel_name',
            'b.type_name',
            'b.materiel_unit',
            'c.storage_name',
            'a.in_storage_num',
            'b.is_use_serial'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('storage as c', 'c.id', '=', 'a.storage_id')
            ->where('a.delete_flag', 0)
            ->whereIn('type_id', $id)
            ->get()->toArray();

        $arr = [];
        foreach ($storageManageInfo as $value) {
            if (!isset($arr[$value['type_id']])) {
                $arr[$value['type_id']] = [
                    'type_id' => $value['type_id'],
                    'materiel_name' => $value['materiel_name'],
                    'type_name' => $value['type_name'],
                    'materiel_unit' => $value['materiel_unit'],
                    'is_use_serial' => $value['is_use_serial'],
                ];

                $arr[$value['type_id']]['storage_manage_info'][] = [
                    'storage_manage_id' => $value['storage_manage_id'],
                    'storage_name' => $value['storage_name'],
                    'storage_id' => $value['storage_id'],
                    'in_storage_num' => $value['in_storage_num'],
                    'shelf_location_info' => self::logShelfInfo($value['type_id'], $value['storage_id'])
                ];
            } else {
                $arr[$value['type_id']]['storage_manage_info'][] = [
                    'storage_manage_id' => $value['storage_manage_id'],
                    'storage_name' => $value['storage_name'],
                    'storage_id' => $value['storage_id'],
                    'in_storage_num' => $value['in_storage_num'],
                    'shelf_location_info' => self::logShelfInfo($value['type_id'], $value['storage_id'])
                ];
            }
        }

        return array_values($arr);
    }

    private static function logShelfInfo($typeId, $storageId)
    {
        DB::enableQueryLog();
        $inShelfInfo = LogInStorageModel::logInShelfInfo($typeId, $storageId);
        $slq = DB::getQueryLog();
        $outShelfInfo = LogOutStorageModel::logOutShelfInfo($typeId, $storageId);

        $res = [];
        foreach ($inShelfInfo as $value) {
            if (!empty($inShelfInfo)) {
                foreach ($inShelfInfo as $value) {
                    $res[$value['location_id']] = [
                        'shelf_id' => empty($value['shelf_id']) ? '' : $value['shelf_id'],
                        'shelf_name' => empty($value['shelf_name']) ? '' : $value['shelf_name'],
                        'location_id' => empty($value['location_id']) ? '' : $value['location_id'],
                        'location_name' => empty($value['location_name']) ? '' : $value['location_name'],
                        'operate_num' => empty($value['operate_num']) ? '' : $value['operate_num'],
                    ];
                }

                if (!empty($outShelfInfo)) {
                    // 对输出数组,处理对比消减逻辑
                    foreach ($outShelfInfo as $val) {
                        if (isset($res[$val['location_id']])) {
                            $res[$val['location_id']]['operate_num'] -= $val['operate_num'];
                        }
                    }
                }
            }
        }

        return array_values($res);
    }

    /*套餐预估数量
     备：杨杰提:2024/5/11
    套餐的预估数量为组件，能够组合成的套餐
    例：套餐1、组件  矿泉水两瓶、纸箱一个，库存矿泉水100瓶，纸箱50个，可组成50套
    套餐1、组件矿泉水两瓶、库存矿泉水101瓶，可组成50套1瓶
    */
    private static function forecastingOfProductUsefulNum($productId)
    {
        $productContentInfo = MaterielProductContentModel::query()
            ->where([
                'delete_flag' => 0,
                'product_id' => $productId
            ])->get();
        if (empty($productContentInfo->toArray())) return '0套';
        if (!empty($productContentInfo->toArray())) {
            $productContentInfo = $productContentInfo->toArray();
            /*$directInStorageProductNum = SerialNumberModel::where([
                'goods_id' => $productId,
                'package_id' => $productId,
                'status' => 1,
                'delete_flag' => 0
            ])->count();*/
            $arr = [];
            foreach ($productContentInfo as $value) {
                $info = StorageManageModel::query()
                    ->select(
                        'type_id',
                        DB::raw('SUM(in_storage_num) as num')
                    )
                    ->where([
                        'type_id' => $value['type_id'],
                        'delete_flag' => 0
                    ])->first();
                if (empty($info)) return '0套';
                $arr[] = 0;
                if (!empty($value['num'])) {
                    //套餐组件虚拟库存数量/套餐组件的数量
                    $arr[] = floor($info['num'] / $value['num']);
                }
                if (count($productContentInfo) == 1) {
                    $intNum = $info['num'] / $value['num'];
                    $decimalsNum = $info['num'] / $value['num'] - $intNum;
                    $intNum = (int)$intNum . '套';
                    if (!empty($decimalsNum)) {
                        $intNum .= $decimalsNum .
                            MaterielTypeModel::query()->where([
                                'id' => $value['type_id']
                            ])->value('materiel_unit');
                    }
                    return $intNum;//套餐的组件数量为1时，返回组成套餐数和余数
                }
            }
            $min = empty($arr) ? 0 : (int)min($arr);
            return $min . '套';//套餐的组件数量多个时，返回组成套餐数
        }
    }

    static public function list($parentId, $data, $storageIdArr = [])
    {
        $keyword = '';
        if (isset($data['keyword'])) {
            if (!empty($data['keyword'])) {
                $keyword = $data['keyword'];
            } elseif (intval($keyword) === 0) {
                $keyword = 0;
            }
        }
        $condition = [];
        if (!empty($data['materiel_class_id'])) {
            $condition['c.id'] = ['EQ' => $data['materiel_class_id']];
        }

        if (isset($data['is_product_materiel'])) {
            $condition['a.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        if (isset($data['is_product_storage'])) {
            $condition['e.is_product_storage'] = ['EQ' => $data['is_product_storage']];
        }

        $result = [];
        switch ($data['order_type']) {
            case 0:
                $result = self::defaultOrder($parentId, $keyword, $condition, $data, $storageIdArr);
                break;
            case 1:
                $result = self::orderByInstorageNum($parentId, $keyword, $condition, $data, $storageIdArr);
                break;
            case 2:
                $result = self::orderByCharset($parentId, $keyword, $condition, $data, $storageIdArr);
                break;
        }


        if (!$data['user_type']) {
            $storageInfo = StorageModel::getSelfStorageInfo([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ]);

            if ($data['order_type'] == 2) {
                foreach ($result as &$value) {
                    $value['is_operate'] = 1;
                }
            } else {
                foreach ($result['data'] as &$value) {
                    $value['is_operate'] = 1;
                }
            }
        } else {
            $storageInfo = StorageModel::getSelfStorageInfo([
                'user_id' => $data['user_id'],
                'delete_flag' => 0
            ]);

            if ($data['is_share_storage_operate']) {
                if ($data['order_type'] == 2) {
                    foreach ($result as &$value) {
                        $value['is_operate'] = 1;
                    }
                } else {
                    foreach ($result['data'] as &$value) {
                        $value['is_operate'] = 1;
                    }
                }
            } else {
                if ($data['order_type'] == 2) {
                    foreach ($result as &$value) {
                        $materielTypeInfo = MaterielTypeModel::where('id', $value['type_id'])->first();
                        $value['selling_price'] = $materielTypeInfo['selling_price'];
                        $value['lower_selling_price'] = $materielTypeInfo['lower_selling_price'];
                        if (in_array($value['storage_id'], $storageInfo)) {
                            $value['is_operate'] = 1;
                        } else {
                            $value['is_operate'] = 0;
                        }
                    }
                } else {
                    foreach ($result['data'] as &$value) {
                        if (in_array($value['storage_id'], $storageInfo)) {
                            $value['is_operate'] = 1;
                        } else {
                            $value['is_operate'] = 0;
                        }
                    }
                }
            }
        }

        return $result;
    }

    //首字母排序
    private static function orderByCharset($parentId, $keyword, $condition, $data, $storageIdArr = [])
    {
        $result = StorageManageModel::orderByCharset($parentId, $keyword, $condition, $data);
        $totalNum = 0;
        if (!empty($result)) {
            $list = [];
            foreach ($result as &$value) {
                $materielTypeInfo = MaterielTypeModel::where('id', $value['type_id'])->first();
                $value['materiel_name'] = $materielTypeInfo['materiel_name'];
                $value['type_name'] = $materielTypeInfo['type_name'];
                $value['materiel_no'] = $materielTypeInfo['materiel_no'];
                $value['materiel_img'] = $materielTypeInfo['materiel_img'];
                $value['is_product_materiel'] = $materielTypeInfo['is_product_materiel'];
                $value['remark'] = $materielTypeInfo['remark'];
                $value['is_use_serial'] = $materielTypeInfo['is_use_serial'];
                $value['materiel_unit'] = $materielTypeInfo['materiel_unit'];
                $value['lower_selling_price'] = $materielTypeInfo['lower_selling_price'];
                $value['selling_price'] = $materielTypeInfo['selling_price'];

                if (!empty($value['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $value['materiel_img']), function ($v) {
                        return $v !== '';
                    });

                    $value['materiel_img'] = $materielImg[0];
                }

                if ($materielTypeInfo['is_product_materiel'] == 1) {
                    $productList = MaterielProductContentModel::select(
                        'a.id',
                        'b.materiel_name',
                        'b.type_name',
                        'b.materiel_img',
                        'b.materiel_no',
                        'a.product_id',
                        'a.num',
                        'a.price',
                        'a.type_id',
                        'a.total_price'
                    )
                        ->from('materiel_product_content as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                        ->where('a.product_id', $value['type_id'])->get()->toArray();

                    $value['forecasting_num'] = self::forecastingOfProductUsefulNum($value['type_id']);

                    foreach ($productList as &$val) {
                        if (!empty($val['materiel_img'])) {
                            $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                                return $v !== '';
                            });
                            $val['materiel_img'] = $materielImg[0];
                        }
                    }

                    $value['product_content'] = $productList;
                } else {
                    $value['forecasting_num'] = '0套';
                    $value['product_content'] = [];
                }

                if (!empty($storageIdArr)) {
                    if (in_array($value['storage_id'], $storageIdArr)) {
                        $list[] = $value;
                    }
                }
                $totalNum += $value['in_storage_num'];
            }

            if (!empty($storageIdArr)) $result = $list;
        }

        return $result;
    }

    //库存数排序
    private static function orderByInstorageNum($parentId, $keyword, $condition, $data, $storageIdArr = [])
    {
        $result = StorageManageModel::list($parentId, $keyword, $condition, $data);

        $test1 = [];
        foreach ($result as $vv1) {
            $test1[$vv1['type_id']][] = $vv1;

        }

        $arr1 = [];
        foreach ($test1 as $vaa) {
            foreach ($vaa as $vaaa) {
                $arr1[] = $vaaa;
            }
        }

        $keywordLength = strlen($keyword);
        $arr = [];

        foreach ($arr1 as $key => $value) {
            if (substr($value['materiel_name'], 0, $keywordLength) == $keyword) {
                $arr[$key] = $value;
                unset($arr1[$key]);
            }
        }

        foreach ($arr1 as $k => $val) {
            if (preg_match('/' . $data['keyword'] . '/', $val['materiel_name'])) {
                $arr[$k] = $val;
                unset($arr1[$k]);
            }
        }

        foreach ($arr1 as $k1 => $v1) {
            $arr[$k1] = $v1;
        }

        if ($data['order_by'] == 'desc') {
            usort($arr, function ($a, $b) {
                if ($a['in_storage_num'] == $b['in_storage_num']) {
                    return 0;
                }
                return ($a['in_storage_num'] > $b['in_storage_num']) ? -1 : 1;
            });
        } else {
            usort($arr, function ($a, $b) {
                if ($a['in_storage_num'] == $b['in_storage_num']) {
                    return 0;
                }
                return ($a['in_storage_num'] > $b['in_storage_num']) ? 1 : -1;
            });
        }
        if (!empty($arr)) {
            $list = [];
            foreach ($arr as $key => &$val) {
                if (!empty($val['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                        return $v !== '';
                    });

                    $val['materiel_img'] = $materielImg[0];
                }

                if ($val['is_product_materiel'] == 1) {
                    $productList = MaterielProductContentModel::select(
                        'a.id',
                        'b.materiel_name',
                        'b.type_name',
                        'b.materiel_img',
                        'b.materiel_no',
                        'a.product_id',
                        'a.num',
                        'a.price',
                        'a.type_id',
                        'a.total_price'
                    )
                        ->from('materiel_product_content as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                        ->where('a.product_id', $val['type_id'])->get()->toArray();

                    foreach ($productList as &$v) {
                        if (!empty($v['materiel_img'])) {
                            $materielImg = array_filter(explode(',', $v['materiel_img']), function ($v) {
                                return $v !== '';
                            });
                            $v['materiel_img'] = $materielImg[0];
                        }
                    }

                    $val['product_content'] = $productList;
                } else {
                    $val['product_content'] = [];
                }
                if (!empty($storageIdArr)) {
                    if (in_array($val['storage_id'], $storageIdArr)) {
                        $list[] = $val;
                    }
                }
            }
            if (!empty($storageIdArr)) $arr = $list;
        }
        $totalNum = 0;
        if (!empty($arr)) {
            foreach ($arr as $aVal) {
                $totalNum += $aVal['in_storage_num'];
            }
        }
        $currentPage = $data['currentPage'];
        $result = array_slice(array_values($arr), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);

        foreach ($result as &$value) {
            if ($value['is_product_materiel']) {
                $value['forecasting_num'] = self::forecastingOfProductUsefulNum($value['type_id']);
            } else {
                $value['forecasting_num'] = '0套';
            }
        }

        return [
            'total' => count($arr),
            'total_num' => $totalNum,
            'current_page' => $data['currentPage'],
            'next_page_url' => count($result) < $data['pageSize'] ? null : config('app.url') . "storage_manage_list?=" . ($data['currentPage'] + 1),
            'prev_page_url' => $data['currentPage'] == 1 ? null : config('app.url') . "storage_manage_list?=" . ($currentPage - 1),
            "path" => config('app.url') . "storage_manage_list",
            "to" => $data['currentPage'] * $data['pageSize'],
            'data' => $result,
            "per_page" => $data['pageSize']
        ];
    }

    private static function defaultOrderCommon($arr)
    {
        if (!empty($arr)) {
            foreach ($arr as $key => &$val) {

                if (!empty($val['materiel_img'])) {
                    if (strpos($val['materiel_img'], ',') !== false) {
                        $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                            return $v !== '';
                        });
                        $val['materiel_img'] = $materielImg[0] ?? '';
                    }
                }
                if ($val['is_product_materiel'] == 1) {
                    $productList = MaterielProductContentModel::select(
                        'a.id',
                        'b.materiel_name',
                        'b.type_name',
                        'b.materiel_img',
                        'b.materiel_no',
                        'a.product_id',
                        'a.num',
                        'a.price',
                        'a.type_id',
                        'a.total_price'
                    )
                        ->from('materiel_product_content as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                        ->where('a.product_id', $val['type_id'])->get()->toArray();

                    foreach ($productList as &$v) {
                        if (!empty($v['materiel_img'])) {
                            $materielImg = array_filter(explode(',', $v['materiel_img']), function ($v) {
                                return $v !== '';
                            });
                            if (empty($materielImg[0]) && !empty($materielImg[1])) {
                                $materielImg[0] = $materielImg[1];
                            }
                            $v['materiel_img'] = $materielImg[0] ?? 0;
                        }
                    }

                    $arr[$key]['product_content'] = $productList;
                } else {
                    $arr[$key]['product_content'] = [];
                }
            }

            return $arr;
        }
        return [];
    }

    public static function alertSort($parentId, $keyword, $condition, $data)
    {
        return self::defaultOrderCommon(StorageManageModel::list($parentId, $keyword, $condition, $data, ['sort_flag' => 1]));
    }

    //默认排序-未达到预警数
    public static function notAlertSort($parentId, $keyword, $condition, $data)
    {
        $result = StorageManageModel::list($parentId, $keyword, $condition, $data, ['sort_flag' => 0]);
        usort($result, function ($a, $b) {
            if (!$a['sort_flag']) {
                if ($a['in_storage_num'] == $b['in_storage_num']) {
                    return 0;
                }
                return ($a['in_storage_num'] > $b['in_storage_num']) ? -1 : 1;
            }
            return true;
        });

        $test1 = [];
        foreach ($result as $vv1) {
            $test1[$vv1['type_id']][] = $vv1;

        }

        $arr1 = [];
        foreach ($test1 as $vaa) {
            foreach ($vaa as $vaaa) {
                $arr1[] = $vaaa;
            }
        }

        $keywordLength = strlen($keyword);
        $arr = [];

        foreach ($arr1 as $key => $value) {
            if (substr($value['materiel_name'], 0, $keywordLength) == $keyword) {
                $arr[$key] = $value;
                unset($arr1[$key]);
            }
        }

        foreach ($arr1 as $k => $val) {
            if (preg_match('/' . $data['keyword'] . '/', $val['materiel_name'])) {
                $arr[$k] = $val;
                unset($arr1[$k]);
            }
        }

        foreach ($arr1 as $k1 => $v1) {
            $arr[$k1] = $v1;
        }

        return self::defaultOrderCommon($arr);
    }

    //默认排序方式-综合排序
    private static function defaultOrder($parentId, $keyword, $condition, $data, $storageIdArr = [])
    {
        $alertSort = self::alertSort($parentId, $keyword, $condition, $data);
        $notAlertSort = self::notAlertSort($parentId, $keyword, $condition, $data);

        if (!empty($alertSort) && !empty($notAlertSort)) {
            $arr = array_merge($alertSort, $notAlertSort);
        } else if (!empty($alertSort) && empty($notAlertSort)) {
            $arr = $alertSort;
        } else {
            $arr = $notAlertSort;
        }
        if (!empty($arr) && !empty($storageIdArr)) {
            $list = [];
            foreach ($arr as $aVal) {
                if (in_array($aVal['storage_id'], $storageIdArr)) {
                    $list[] = $aVal;
                }
            }
            $arr = $list;
        }
        $totalNum = 0;
        if (!empty($arr)) {
            foreach ($arr as $aVal) {
                $totalNum += $aVal['in_storage_num'];
            }
        }

        $currentPage = $data['currentPage'];
        $result = array_slice(array_values($arr), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);

        foreach ($result as &$value) {
            if ($value['is_product_materiel']) {

                //备：杨杰提:2024/5/11
                //套餐的预估数量为组件，能够组合成的套餐
                //例：套餐1、组件  矿泉水两瓶、纸箱一个，库存矿泉水100瓶，纸箱50个，可组成50套
                //套餐1、组件矿泉水两瓶、库存矿泉水101瓶，可组成50套1瓶
                $value['forecasting_num'] = self::forecastingOfProductUsefulNum($value['type_id']);

            } else {
                $value['forecasting_num'] = '0套';
            }

        }
        return [
            'total_num' => $totalNum,
            'total' => count($arr),
            'current_page' => $currentPage,
            'next_page_url' => count($result) < $data['pageSize'] ? null : config('app.url') . "storage_manage_list?=" . ($data['currentPage'] + 1),
            'prev_page_url' => $currentPage == 1 ? null : config('app.url') . "storage_manage_list?=" . ($currentPage - 1),
            "path" => config('app.url') . "storage_manage_list",
            "to" => $currentPage * $data['pageSize'],
            'data' => array_values($result),
            "per_page" => $data['pageSize']
        ];
    }

    /**
     * 审批出库
     * @param $userId
     * @param $mainId
     * @param $data
     * @param $sellId
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/6 17:13
     * @return array
     */
    static public function checkOutStorage($isUseShelf, $userId, $mainId, $data, $sellId = 0, $overflowBreakagePackageInfo)
    {
        if (!empty($data['content'])) {
            self::materielOutStorage($isUseShelf, $userId, $mainId, $data, $sellId);
        }

        if (!empty($overflowBreakagePackageInfo)) {
            self::packageOutStorage($isUseShelf, $userId, $mainId, $data, $overflowBreakagePackageInfo);
        }

        return ['code' => 0, 'msg' => '', 'data' => ''];
    }

    static private function packageOutStorage($isUseShelf, $userId, $mainId, $data, $package)
    {
        //出库信息
        $outStorageNumInfo = [];
        $logPackageInfo = [];

        foreach ($package as $key => $value) {


            foreach ($value['package_content'] as $val) {
                if ($val['in_storage_num'] < $val['total_num']) {
                    throw new Exception('库存剩余数量不足');
                }

                if ($val['virtual_storage_num'] < $val['total_num']) {
                    throw new Exception('库存可预出库剩余数量不足');
                }

                if (!$isUseShelf || $value['shelf_id'] == 0) {
                    $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])
                        ->where('shelf_type', 1)->first();

                    $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $shelfInfo['id'])
                        ->where('location_type', 1)->first();
                } else {
                    $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])->where('id', $value['shelf_id'])->first();

                    if (empty($shelfInfo)) {
                        throw new Exception('无效货架，请重试');
                    }

                    $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $value['shelf_id'])
                        ->where('shelf_location_id', $value['shelf_location_id'])->first();

                    if (empty($shelfLocationInfo)) {
                        throw new Exception('无效库位，请重试');
                    }
                }

                //序列号
                if ($isUseSerial && empty($value['serial_number'])) {
                    throw new Exception('请填写序列号');
                } else if ($isUseSerial && !empty($value['serial_number'])) {
                    $serialNumberInfo = array_filter(explode(',', $value['serial_number']), function ($v) {
                        return $v !== '';
                    });

                    $checkSerialNumber = SerialNumberModel::where([
                        'storage_manage_id' => $value['id'],
                        'delete_flag' => 0,
                    ])->whereIn('serial_no', $serialNumberInfo)->get()->toArray();

                    $arr1 = [];
                    foreach ($checkSerialNumber as $vv1) {
                        if ($vv1['status']) {
                            throw new Exception('序列号：' . $vv1['serial_no'] . '已使用');
                        }

                        $arr1[] = [
                            'id' => $vv1['id'],
                            'status' => 1
                        ];
                    }

                    batch()->update(new SerialNumberModel, $arr1, 'id');
                }

                LogPackageContentModel::insert([
                    'log_package_id' => $logId,
                    'package_id' => $value['package_id'],
                    'storage_id' => $val['storage_id'],
                    'storage_name' => $val['storage_name'],
                    'storage_address' => $val['storage_address'],
                    'materiel_class_id' => $val['materiel_class_id'],
                    'materiel_class_name' => $val['materiel_class_name'],
                    'materiel_class_no' => $val['materiel_class_no'],
                    'materiel_type_id' => $val['type_id'],
                    'materiel_name' => $val['materiel_name'],
                    'type_name' => $val['type_name'],
                    'materiel_no' => $val['materiel_no'],
                    'operate_num' => $val['total_num'],
                    'shelf_id' => $shelfInfo['shelf_id'],
                    'location_id' => $shelfLocationInfo['location_id'],
                    'out_storage_manage_id' => $val['storage_manage_id'],
                    'last_storage_num' => $val['in_storage_num'],
                    'next_storage_num' => $val['in_storage_num'] - $val['total_num'],
                    'all_id_type' => 2,
                    'all_id' => $data['all_id'],
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'created_at' => time()
                ]);

                StorageManageModel::where('id', $val['storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - ' . $val['total_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - ' . $val['total_num'])
                    ]);

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $val['alert_num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $val['id'],
                    $val['storage_name'],
                    $val['total_num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $val['storage_name'],
                    $val['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['total_num'],
                    $val['storage_name'],
                    $val['total_num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $val['id'],
                    $val['alert_num']
                );
            }
        }
        return true;
    }

    static private function materielOutStorage($isUseShelf, $userId, $mainId, $data, $sellId)
    {
        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据

        foreach ($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'a.is_use_serial'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if (empty($materielTypeInfo)) {
                throw new Exception('物料`' . $value['name'] . '-' . $value['type_name'] . '`不存在');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if (empty($storageInfo)) {
                throw new Exception('仓库`' . $value['warehouse'] . '`不存在');
            }

            if (!$isUseShelf || $value['shelf_id'] == 0) {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])
                    ->where('shelf_type', 1)->first();

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $shelfInfo['id'])
                    ->where('location_type', 1)->first();
            } else {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])->where('id', $value['shelf_id'])->first();

                if (empty($shelfInfo)) {
                    return ['code' => 1, 'msg' => '无效货架，请重试', 'data' => ''];
                }

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $value['shelf_id'])
                    ->where('shelf_location_id', $value['shelf_location_id'])->first();

                if (empty($shelfLocationInfo)) {
                    return ['code' => 1, 'msg' => '无效库位，请重试', 'data' => ''];
                }
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            //检查库存中是否存在该物料
            if (empty($storageManageInfo)) {
                throw new Exception('库存中物料`' . $value['name'] . '-' . $value['type_name'] . '`不存在');
            }

            if ($storageManageInfo['in_storage_num'] < $value['num']) {
                throw new Exception('当前库存剩余数量不足，无法完成出库');
            }

//            $logOutPackageData[$key]['storage_manage_id'] = $storageManageInfo['id'];//库存id
//            $logOutPackageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
//            $logOutPackageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
//            $logOutPackageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
//            $logOutPackageData[$key]['out_time'] = strtotime(date('Y-m-d'));//实际出库时间
//            $logOutPackageData[$key]['mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价

            $price = empty($value['price']) ? 0 : $value['price'];

//            $logOutPackageData[$key]['price'] = $data['all_id_type'] == 1?$storageManageInfo['materiel_mean_cost']:$price;
//            $logOutPackageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
//            $logOutPackageData[$key]['all_id'] = $data['all_id'];//单据id
//            $logOutPackageData[$key]['user_id'] = $userId;
//            $logOutPackageData[$key]['main_id'] = $mainId;
//            $logOutPackageData[$key]['created_at'] = time();
//            $logOutPackageData[$key]['num'] = $value['num'];//操作数量

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['shelf_id'] = $shelfInfo['shelf_id'];//货架
            $logOutstorageData[$key]['location_id'] = $shelfLocationInfo['location_id'];//库位
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['sell_price'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark']) ? '' : $data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['created_at'] = time();

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        //生成入库操作记录
        LogOutstorageModel::insert($logOutstorageData);

        //更新库存总数
        foreach ($outstorageNumsData as $val) {
            StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

            //验证是否有预出库，有则跳过此步骤
            $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                ->where('materiel_type_id', $val['type_id'])->first();

            if (empty($prepareInfo)) {
                StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
            }

            MessageService::sendAlertSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $val['alert_num'],
                $datas = ['user_id' => $userId, 'main_id' => $mainId],
                $storageInfo['id'],
                $val['storage_name'],
                $val['num']
            );

            MessageService::sendShortSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $datas = ['user_id' => $userId, 'main_id' => $mainId],
                $val['storage_name'],
                $storageInfo['id']
            );

            MessageService::sendOutSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'] - $val['num'],
                $val['storage_name'],
                $val['num'],
                $datas = ['user_id' => $userId, 'main_id' => $mainId],
                $storageInfo['id'],
                $val['alert_num']
            );
        }

        return true;
    }

    /**
     * @出库
     * @created 在 2021/11/29 19:08 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data ['content] 出库物料商品信息
     * @param $data ['content]['name] 物料名称
     * @param $data ['content]['price] 单价
     * @param $data ['content]['type_name] 物料型号
     * @param $data ['content]['warehouse] 仓库名
     * @param $data ['content]['warehouse_id] 仓库主键id
     * @param $data ['content]['num] 出库操作数量
     * @param $data ['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data ['all_id] 单据id
     * @param $data ['out_storage_time] 出库时间
     * @param $data ['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorage($userId, $mainId, $data, $sellId = 0, $isUseShelf = 0)
    {
        if (empty($data['content'])) {
            return ['code' => 1, 'msg' => '无可出库商品信息', 'data' => ''];
        }

        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据
        $sellGoodsList = [];

        $sellInfo = SellModel::where('id', $data['all_id'])->first();
        foreach ($data['content'] as $key => $value) {
            $shelfId = empty($value['shelf_id']) ? 0 : $value['shelf_id'];
            $locationId = empty($value['location_id']) ? 0 : $value['location_id'];

            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if (empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '物料`' . $value['name'] . '-' . $value['type_name'] . '`不存在', 'data' => ''];
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if (empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`' . $value['warehouse'] . '`不存在', 'data' => ''];
            }

            //物料当前库存信息
            if ($isUseShelf) {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'main_id' => $mainId,
                    'delete_flag' => 0,
                    'shelf_id' => $shelfId,
                    'location_id' => $locationId,
                ])->first();
            } else {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'main_id' => $mainId,
                    'delete_flag' => 0,
                ])->first()->toArray();
            }

            //检查库存中是否存在该物料
            if (empty($storageManageInfo)) {
                return ['code' => 1, 'msg' => '库存中物料`' . $value['name'] . '-' . $value['type_name'] . '`不存在', 'data' => ''];
            }

            if ($storageManageInfo['in_storage_num'] < $value['num']) {
                return ['code' => 1, 'msg' => $value['name'] . '-' . $value['type_name'] . '当前库存剩余数量' . $storageManageInfo['in_storage_num'] . '不足，无法完成出库', 'data' => ''];
            }

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['sell_price'] = $value['price'];//物料均价
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark']) ? '' : $data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['shelf_id'] = $shelfId;
            $logOutstorageData[$key]['location_id'] = $locationId;
            $logOutstorageData[$key]['created_at'] = time();
            $logOutstorageData[$key]['serial_number'] = $value['serial_no'];
            $sellGoodsList[] = [
                'materiel_type_id' => $materielTypeInfo['id'],
                'cost_price' => $storageManageInfo['materiel_mean_cost'],
                'num' => $value['num'],
                'main_id' => $mainId,
//                'user_id' => $userId,
                'sell_id' => $data['all_id'],
                'sell_date' => strtotime($sellInfo['sell_date']),
                'created_at' => time(),
            ];

            $logOutstorageData[$key]['shelf_id'] = $shelfId;
            $logOutstorageData[$key]['location_id'] = $locationId;

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
                'shelf_id' => empty($value['shelf_id']) ? '' : $value['shelf_id'],
                'location_id' => empty($value['location_id']) ? '' : $value['location_id'],

            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        DB::beginTransaction();

        try {
            //生成入库操作记录
            LogOutstorageModel::insert($logOutstorageData);

            //更新库存总数
            foreach ($outstorageNumsData as $val) {
                StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

                //验证是否有预出库，有则跳过此步骤
                if ($sellId != 0) {
//                    $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
//                        ->where('materiel_type_id', $val['type_id'])->first();
                    $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                        ->where('materiel_type_id', $val['type_id'])->where(['shelf_id' => $shelfId, 'location_id' => $locationId])->first();
                    if (empty($prepareInfo)) {
                        StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
                    }
                }

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['alert_num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $val['storage_name'],
                    $storageInfo['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['storage_name'],
                    $val['num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['alert_num']
                );
            }

            SellGoodsListModel::insert($sellGoodsList);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => $returnData];
        } catch (Exception $e) {
            DB::rollback();
            Log::debug('出库：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];
        }
    }

    /**
     *
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data ['content] 出库物料商品信息
     * @param $data ['content]['storage_manage_id] 商品库存id
     * @param $data ['content]['price] 单价
     * @param $data ['content]['num] 出库操作数量
     * @param $data ['content]['batch_info] 批次信息
     * @param $data ['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data ['all_id] 单据id
     * @param $data ['out_storage_time] 出库时间
     * @param $data ['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorageWithBatch($userId, $mainId, $data, $sellId)
    {
        foreach ($data['content'] as $value) {
            foreach ($value['batch_info'] as $val) {
                //出库商品基础信息
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'b.storage_name',
                    'b.storage_address',
                    'a.type_id',
                    'c.materiel_name',
                    'c.materiel_no',
                    'c.type_name',
                    'a.materiel_class_id',
                    'd.class_name',
                    'd.class_no',
                    'materiel_mean_cost',
                    'in_storage_num'
                )
                    ->from('storage_manage as a')
                    ->leftJoin('storage as b', 'b.id', '=', 'a.storage_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                    ->where([
                        'a.id' => $val['storage_manage_id'],
                        'a.delete_flag' => 0
                    ])->first();

                MessageService::sendAlertSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $storageManageInfo['alert_num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $storageManageInfo['storage_name'],
                    $storageManageInfo['storage_id']
                );

                MessageService::sendOutSms(
                    $storageManageInfo['materiel_name'],
                    $storageManageInfo['type_name'],
                    $storageManageInfo['in_storage_num'] - $val['num'],
                    $storageManageInfo['storage_name'],
                    $val['num'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $storageManageInfo['storage_id'],
                    $storageManageInfo['alert_num']
                );

                $outStorageLogInfo[] = [
                    'storage_id' => $storageManageInfo['storage_id'],
                    'storage_name' => $storageManageInfo['storage_name'],
                    'storage_address' => $storageManageInfo['storage_address'],
                    'curr_storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['class_name'],
                    'materiel_class_no' => $storageManageInfo['class_no'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'operate_num' => $val['num'],
                    'last_storage_num' => $storageManageInfo['in_storage_num'],
                    'next_storage_num' => $storageManageInfo['in_storage_num'] - $val['num'],
                    'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'all_id_type' => 2,
                    'all_id' => $sellId,
                    'user_id' => $userId,
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'remark' => $value['remark'],
                    'out_storage_time' => $value['in_storage_time'],
                    'fact_out_time' => time(),
                    'created_at' => time(),
                    'storage_batch_id' => $val['batch_id'],
                ];

                $logOutPackageInfo[] = [
                    'storage_manage_id' => $storageManageInfo['id'],
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_type_id' => $storageManageInfo['type_id'],
                    'storage_id' => $storageManageInfo['storage_id'],
                    'out_time' => $value['in_storage_time'],
                    'num' => $val['num'],
                    'mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'price' => $value['price'],
                    'all_id_type' => 2,
                    'all_id' => $sellId,
                    'user_id' => $userId,
                    'main_id' => $mainId,
                    'created_at' => time(),
                ];

                $outStorageInfo[] = [
                    'id' => $storageManageInfo['id'],
                    'num' => $val['num'],
                ];

                $batchInfo[] = [
                    'id' => $val['batch_id'],
                    'num' => $val['num'],
                ];
            }
        }

        return [
            'data' => $outStorageLogInfo,
            'data1' => $logOutPackageInfo,
            'data2' => $outStorageInfo,
            'data3' => $batchInfo,
        ];
    }

    /**出库撤销回滚数量
     * @created 在 2022/01/11 10:17 创建
     * @param $allIdType 单据类型;1:报损;2:销售;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;
     * @author: Sun Wu
     */
    static public function cancelOut($allIdType, $allId)
    {
        $logOutInfo = LogOutstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if (!empty($logOutInfo)) {
            $item = [];
            foreach ($logOutInfo as $value) {
                if (!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                } else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach ($logOutInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach ($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if (empty($checkStorageManageInfo)) {
                    return 0;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])->increment('in_storage_num', $v['num']);
                StorageManageModel::where([
                    'id' => $v['id']
                ])->increment('virtual_storage_num', $v['num']);
            }

            LogOutstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
            LogOutPackageModel::where([
                'all_id_type' => $allIdType,
                'all_id' => $allId
            ])->update(['is_cancel' => 1]);
        }

        return 1;
    }

    static public function cancelPackageOut($allIdType, $allId)
    {
        $logPackageInfo = LogPackageModel::where('all_id_type', $allIdType)
            ->where('all_id', $allId)->where('is_cancel', 0)->first();

        if (!empty($logPackageInfo)) {
            $logPackageContentInfo = LogPackageContentModel::where([
                'all_id_type' => 4,
                'all_id' => $allId
            ])->get()->toArray();

            foreach ($logPackageContentInfo as $value) {
                StorageManageModel::where('id', $value['out_storage_manage_id'])
                    ->update([
                        'delete_flag' => 0,
                        'in_storage_num' => DB::raw('in_storage_num +' . $value['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num +' . $value['operate_num']),
                    ]);
            }
        }

        LogPackageModel::where('all_id_type', $allIdType)
            ->where('all_id', $allId)
            ->update(['is_cancel' => 1]);

        return 1;
    }

    /**入库撤销回滚数量
     * @created 在 2022/01/11 10:47 创建
     * @param $allIdType 单据类型;1:报溢;2:退货;3:采购;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;2:库存数量不足，无法撤销;
     * @author: Sun Wu
     */
    static public function cancelIn($allIdType, $allId)
    {
        $logInInfo = LogInstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if (!empty($logInInfo)) {
            $item = [];
            foreach ($logInInfo as $value) {
                if (!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                } else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach ($logInInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach ($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if (empty($checkStorageManageInfo)) {
                    return 0;
                }

                if ($checkStorageManageInfo['in_storage_num'] < $v['num']) {
                    return 2;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])
                    ->update([
                        'virtual_storage_num' => DB::raw('virtual_storage_num - ' . $v['num']),
                        'in_storage_num' => DB::raw('in_storage_num - ' . $v['num']),
                    ]);
            }

            LogInstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
        }

        return 1;
    }

    static public function cancelPackageIn($type, $id)
    {
        $logPackageInfo = LogPackageModel::where(['all_id_type' => $type, 'all_id' => $id, 'is_cancel' => 0])
            ->first();

        try {
            if (!empty($logPackageInfo)) {
                $logPackageContentInfo = LogPackageContentModel::where([
                    'all_id_type' => 5,
                    'all_id' => $id,
                ])
                    ->get()->toArray();

                foreach ($logPackageContentInfo as $value) {
                    $storageManageInfo = StorageManageModel::where([
                        'id' => $value['out_storage_manage_id'],
                        'delete_flag' => 0
                    ])
                        ->first()->toArray();
                    //库存中无此商品
                    if (empty($storageManageInfo)) {
                        return 0;
                    }

                    //库存数不足
                    if ($storageManageInfo['in_storage_num'] < $value['operate_num']) {
                        return 3;
                    }

                    StorageManageModel::where('id', $value['out_storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num - ' . $value['operate_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num - ' . $value['operate_num']),
                        ]);
                }
            }

            LogPackageModel::where(['all_id_type' => $type, 'all_id' => $id, 'is_cancel' => 0])
                ->update(['is_cancel' => 1]);

            DB::commit();
            return 1;
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('套餐入库撤销异常:' . var_export($e->getMessage(), true));
            return 2;
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data ['content] 入库物料商品信息
     * @param array $data ['content]['name'] 物料名称
     * @param array $data ['content]['type_name'] 物料名称
     * @param array $data ['content]['warehouse'] 仓库名
     * @param array $data ['content]['warehouse_id'] 仓库主键id
     * @param array $data ['content]['num] 操作数量
     * @param array $data ['in_storage_time] 入库时间
     * @param array $data ['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data ['all_id] 单据id
     * @param array $data ['remark] 备注
     * @return array
     * @author: ZLF
     */
    static public function zongInStorage($userId, $mainId, $data, $flag = 0)
    {
        $logInstorageData = [];//入库操作记录数据
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];
        foreach ($data['content'] as $key => $value) {

            //为了兼容版本 判断shelf_id 和location_id
            if (empty($value['shelf_id']) || empty($value['location_id'])) {
                /*  $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                 $location_id = ShelfService::get_default($shelf_id,2)['id']; */
                $sfData = ShelfService::get_default($value['warehouse_id']);
                if (!empty($sfData)) {
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id, 2);
                    $location_id = $lData['id'];
                } else {
                    $shelf_id = 0;
                    $location_id = 0;
                    $value['shelf_id'] = 0;
                    $value['location_id'] = 0;
                }
            } else {
                $shelf_id = $value['shelf_id'];
                $location_id = $value['location_id'];
            }

            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'a.id' => $value['goods_id'],
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId
                ])
                ->first();

            if (empty($materielTypeInfo)) {
                throw new Exception('商品信息不存在，无法入库');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'shelf_id' => $shelf_id,
                'location_id' => $location_id
            ])->first();

            if (empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'virtual_storage_num' => $value['num'],
                    'main_id' => $mainId,
                    'in_storage_time' => time(),

                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                    'serial_no' => empty($value['serial_no']) ? '' : $value['serial_no'],
                ];

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $value['num'],
                    $value['num']
                );
            } else {

                if (!empty($value['serial_no'])) {

                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost'],
                        'serial_no' => $value['serial_no'],
                    ];
                } else {

                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost']
                    ];
                }

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $value['num'],
                    $value['num'] + $storageManageInfo['in_storage_num']
                );

                $logInstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//当前库存id
            }

            $logInstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logInstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logInstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logInstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号

            $logInstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logInstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logInstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logInstorageData[$key]['type'] = 0;//入库日志类型;0:入库;1:调拨入库;2:直接入库;

            $logInstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logInstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logInstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logInstorageData[$key]['last_storage_id'] = 0;//调拨前所在仓库id

            $logInstorageData[$key]['operate_num'] = $value['num'];//操作数量

            $logInstorageData[$key]['last_storage_num'] = empty($storageManageInfo['in_storage_num']) ? 0 : $storageManageInfo['in_storage_num'];//操作前库存数

            $logInstorageData[$key]['materiel_mean_cost'] = empty($storageManageInfo['materiel_mean_cost']) ? 0 : $storageManageInfo['materiel_mean_cost'];//物料均价

            if (!empty($storageManageInfo)) {
                $logInstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] + $value['num'];//操作后库存数
            } else {
                $logInstorageData[$key]['next_storage_num'] = $value['num'];//操作后库存数

            }
            $logInstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报溢;2:退货;3:采购;
            $logInstorageData[$key]['in_storage_time'] = strtotime($data['in_storage_time']);//入库时间
            $logInstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logInstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logInstorageData[$key]['main_id'] = $mainId;//主账号id
            $logInstorageData[$key]['remark'] = empty($data['remark']) ? '' : $data['remark'];
            $logInstorageData[$key]['created_at'] = time();
            $logInstorageData[$key]['serial_number'] = !empty($value['serial_no']) ? $value['serial_no'] : '';
            $logInstorageData[$key]['shelf_id'] = $shelf_id;
            $logInstorageData[$key]['location_id'] = $location_id;

        }

        DB::beginTransaction();

        try {

            if (!empty($instorageNumsData)) {

                //更新库存总数
                foreach ($instorageNumsData as $key => $value) {
                    $bool = StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + ' . $value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + ' . $value['in_storage_num']),
                            'delete_flag' => 0
                        ]);

                    $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                    $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    } while (!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );
//                    if(!$flag){
                    if (!empty($value['serial_no'])) {
                        //处理序列号
                        $serialData = array_filter(
                            explode(',', $value['serial_no']), function ($v) {
                            return $v !== '';
                        }
                        );

                        $checkSerialNumber = SerialNumberModel::where([
                            'status' => 1,
                            'delete_flag' => 0,
                            'goods_id' => $value['type_id']
                        ])->whereIn('serial_no', $serialData)
                            ->first();

                        if (!empty($checkSerialNumber)) {
                            throw new Exception('序列号:' . $checkSerialNumber['serial_no' . '未出库，无法退货']);
                        }

                        SerialNumberModel::where([
                            'delete_flag' => 0,
                            'goods_id' => $value['type_id']
                        ])->whereIn('serial_no', $serialData)->update(['status' => 1]);

                        if (!empty($serial_no_res['code'])) {
                            return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                        }
                    }
//                    }
                }
            }

            if (!empty($arr)) {
                foreach ($arr as $v) {
                    foreach ($logInstorageData as $k1 => $v1) {
                        if ($v1['materiel_type_id'] == $v['type_id']) {
                            $arr = [
                                'materiel_class_id' => $v['materiel_class_id'],
                                'materiel_class_name' => $v['materiel_class_name'],
                                'materiel_class_no' => $v['materiel_class_no'],
                                'type_id' => $v['type_id'],
                                'materiel_name' => $v['materiel_name'],
                                'type_name' => $v['type_name'],
                                'materiel_no' => $v['materiel_no'],
                                'storage_id' => $v['storage_id'],
                                'storage_name' => $v['storage_name'],
                                'storage_address' => $v['storage_address'],
                                'in_storage_num' => $v['in_storage_num'],
                                'virtual_storage_num' => $v['virtual_storage_num'],
                                'main_id' => $mainId,
                                'in_storage_time' => time(),

                                'shelf_id' => $v['shelf_id'],
                                'location_id' => $v['location_id'],
                            ];

                            $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                            $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                            $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                                ->where('batch_no', $batchNo)->first();

                            do {
                                $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                            } while (!empty($checkBatchNo));

                            $insertId = StorageManageModel::insertGetId($arr);

                            $logInstorageData[$k1]['curr_storage_manage_id'] = $insertId;

                            $batchId = MaterielService::createBatchInfoGetId(
                                $batchNo,
                                $insertId,
                                0,
                                $v['in_storage_num'],
                                0,
                                $mainId
                            );

                            $logInstorageData[$k1]['batch_id'] = $batchId;
//                            if(!$flag){
                            if (!empty($v['serial_no'])) {
                                //处理序列号
                                $serial_no_res = SerialNumberModel::inSerialNumber($mainId, $v['serial_no'], $v['in_storage_num'], $v['type_id'], $insertId, $batchNo);
                                if (!empty($serial_no_res['code'])) {
                                    return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                                }
                            }
                        }
//                        }
                    }
                }
            }

            if (!empty($logInstorageData)) {
                foreach ($logInstorageData as &$lv) {
                    if (empty($lv['batch_id'])) $lv['batch_id'] = 0;
                }
            }
            //生成入库操作记录
            $bool = LogInstorageModel::insert($logInstorageData);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '入库失败！', 'data' => ''];
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data ['content] 入库物料商品信息
     * @param array $data ['content]['name'] 物料名称
     * @param array $data ['content]['type_name'] 物料名称
     * @param array $data ['content]['warehouse'] 仓库名
     * @param array $data ['content]['warehouse_id'] 仓库主键id
     * @param array $data ['content]['num] 操作数量
     * @param array $data ['in_storage_time] 入库时间
     * @param array $data ['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data ['all_id] 单据id
     * @param array $data ['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function oldInStorage($userId, $mainId, $data, $flag = 0)
    {
        $logInstorageData = [];//入库操作记录数据
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];
        foreach ($data['content'] as $key => $value) {

            //为了兼容版本 判断shelf_id 和location_id
            if (empty($value['shelf_id']) || empty($value['location_id'])) {
                /*  $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                 $location_id = ShelfService::get_default($shelf_id,2)['id']; */
                $sfData = ShelfService::get_default($value['warehouse_id']);
                if (!empty($sfData)) {
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id, 2);
                    $location_id = $lData['id'];
                } else {
                    $shelf_id = 0;
                    $location_id = 0;
                    $value['shelf_id'] = 0;
                    $value['location_id'] = 0;
                }
            } else {
                $shelf_id = $value['shelf_id'];
                $location_id = $value['location_id'];
            }

            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'a.id' => $value['goods_id'],
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                ])
                ->first();


            if (empty($materielTypeInfo)) {
                throw new Exception('商品信息不存在，无法入库');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'shelf_id' => $shelf_id,
                'location_id' => $location_id
            ])->first();

            if (empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'virtual_storage_num' => $value['num'],
                    'main_id' => $mainId,
                    'in_storage_time' => time(),

                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                    'serial_no' => empty($value['serial_no']) ? '' : $value['serial_no'],
                ];

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $value['num'],
                    $value['num']
                );
            } else {

                if (!empty($value['serial_no'])) {

                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost'],
                        'serial_no' => $value['serial_no'],
                    ];
                } else {

                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost'],
                        'serial_no' => $value['serial_no'],
                    ];
                }

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas = ['user_id' => $userId, 'main_id' => $mainId],
                    $value['num'],
                    $value['num'] + $storageManageInfo['in_storage_num']
                );

                $logInstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//当前库存id
            }

            $logInstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logInstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logInstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logInstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号

            $logInstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logInstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logInstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logInstorageData[$key]['type'] = 0;//入库日志类型;0:入库;1:调拨入库;2:直接入库;

            $logInstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logInstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logInstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logInstorageData[$key]['last_storage_id'] = 0;//调拨前所在仓库id

            $logInstorageData[$key]['operate_num'] = $value['num'];//操作数量

            $logInstorageData[$key]['last_storage_num'] = empty($storageManageInfo['in_storage_num']) ? 0 : $storageManageInfo['in_storage_num'];//操作前库存数

            $logInstorageData[$key]['materiel_mean_cost'] = empty($storageManageInfo['materiel_mean_cost']) ? 0 : $storageManageInfo['materiel_mean_cost'];//物料均价

            if (!empty($storageManageInfo)) {
                $logInstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] + $value['num'];//操作后库存数
            } else {
                $logInstorageData[$key]['next_storage_num'] = $value['num'];//操作后库存数

            }
            $logInstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报溢;2:退货;3:采购;
            $logInstorageData[$key]['in_storage_time'] = strtotime($data['in_storage_time']);//入库时间
            $logInstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logInstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logInstorageData[$key]['main_id'] = $mainId;//主账号id
            $logInstorageData[$key]['remark'] = empty($data['remark']) ? '' : $data['remark'];
            $logInstorageData[$key]['created_at'] = time();
            $logInstorageData[$key]['serial_number'] = !empty($value['serial_no']) ? $value['serial_no'] : '';
            $logInstorageData[$key]['shelf_id'] = $shelf_id;
            $logInstorageData[$key]['location_id'] = $location_id;

        }

        DB::beginTransaction();

        try {

            if (!empty($instorageNumsData)) {

                //更新库存总数
                foreach ($instorageNumsData as $key => $value) {
                    $bool = StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + ' . $value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + ' . $value['in_storage_num']),
                            'delete_flag' => 0
                        ]);

                    $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                    $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    } while (!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );

                    if (!empty($value['serial_no'])) {
                        $serialInfo = array_filter(
                            explode(',', $value['serial_no']), function ($v) {
                            return $v !== '';
                        }
                        );

                        $checkSerialNumber = SerialNumberModel::where([
                            'status' => 1,
                            'goods_id' => $value['type_id'],
                            'delete_flag' => 0
                        ])->whereIn('serial_no', $serialInfo)
                            ->first();

                        if (!empty($checkSerialNumber)) {
                            throw new Exception('序列号:' . $checkSerialNumber['serial_no' . '未出库，无法退货']);
                        }

                        SerialNumberModel::where([
                            'goods_id' => $value['type_id'],
                            'delete_flag' => 0
                        ])->whereIn('serial_no', $serialInfo)
                            ->update([
                                'status' => 1,
                                'storage_manage_id' => $value['id']
                            ]);
                    }

//                    SerialNumberModel::where('goods_id', )
//
//                    SerialNumberModel::where(['serial_no' => $serial_data,'status' => SerialNumberModel::USEDSTATUS,
//                        'goods_id' => $number_info['goods_id'],
//                    ])->update([
//                        'status' => SerialNumberModel::UNUSEDSTATUS,
//                        'storage_manage_id' => $value['id']
//                    ]);

//                    if(!$flag){
                    if (!empty($value['serial_no'])) {
//                            //处理序列号
                        $serial_no_res = SerialNumberModel::inSerialNumber($mainId, $value['serial_no'], $value['in_storage_num'], $value['type_id'], $value['id'], $batchNo);
//                            if(!empty($serial_no_res['code'])){
//                                return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
//                            }
                    }
//                    }
                }
            }

            if (!empty($arr)) {
                foreach ($arr as $v) {
                    foreach ($logInstorageData as $k1 => $v1) {
                        if ($v1['materiel_type_id'] == $v['type_id']) {
                            $arr = [
                                'materiel_class_id' => $v['materiel_class_id'],
                                'materiel_class_name' => $v['materiel_class_name'],
                                'materiel_class_no' => $v['materiel_class_no'],
                                'type_id' => $v['type_id'],
                                'materiel_name' => $v['materiel_name'],
                                'type_name' => $v['type_name'],
                                'materiel_no' => $v['materiel_no'],
                                'storage_id' => $v['storage_id'],
                                'storage_name' => $v['storage_name'],
                                'storage_address' => $v['storage_address'],
                                'in_storage_num' => $v['in_storage_num'],
                                'virtual_storage_num' => $v['virtual_storage_num'],
                                'main_id' => $mainId,
                                'in_storage_time' => time(),

                                'shelf_id' => $v['shelf_id'],
                                'location_id' => $v['location_id'],
                            ];

                            $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                            $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                            $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                                ->where('batch_no', $batchNo)->first();

                            do {
                                $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                            } while (!empty($checkBatchNo));

                            $insertId = StorageManageModel::insertGetId($arr);

                            $logInstorageData[$k1]['curr_storage_manage_id'] = $insertId;

                            $batchId = MaterielService::createBatchInfoGetId(
                                $batchNo,
                                $insertId,
                                0,
                                $v['in_storage_num'],
                                0,
                                $mainId
                            );

                            $logInstorageData[$k1]['batch_id'] = $batchId;
//                            if(!$flag){
                            if (!empty($v['serial_no'])) {
                                //处理序列号
                                $serial_no_res = SerialNumberModel::inSerialNumber($mainId, $v['serial_no'], $v['in_storage_num'], $v['type_id'], $insertId, $batchNo);
                                if (!empty($serial_no_res['code'])) {
                                    return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                                }
                            }
//                            }
                        }
                    }
                }
            }

            if (!empty($logInstorageData)) {
                foreach ($logInstorageData as &$lv) {
                    if (empty($lv['batch_id'])) $lv['batch_id'] = 0;
                }
            }
            //生成入库操作记录
            $bool = LogInstorageModel::insert($logInstorageData);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '采购入库失败 ', 'data' => ''];
        }
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @modify 在 2022/05/06 16:32 By Sun Wu
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data ['content] 入库物料商品信息
     * @param array $data ['content]['name'] 物料名称
     * @param array $data ['content]['type_name'] 物料名称
     * @param array $data ['content]['warehouse'] 仓库名
     * @param array $data ['content]['warehouse_id'] 仓库主键id
     * @param array $data ['content]['num] 操作数量
     * @param array $data ['in_storage_time] 入库时间
     * @param array $data ['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data ['all_id] 单据id
     * @param array $data ['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function inStorage($isUseShelf, $userId, $mainId, $data, $batchTitle)
    {

        $logInstorageData = [];//入库操作记录数据
        $existLogInstorageData = [];
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];

        foreach ($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class',
                'a.is_use_serial'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if (!$isUseShelf || $value['shelf_id'] == 0) {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])
                    ->where('shelf_type', 1)->first();

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $shelfInfo['id'])
                    ->where('location_type', 1)->first();
            } else {
                $shelfInfo = StorageShelfModel::where('storage_id', $value['warehouse'])->where('id', $value['shelf_id'])->first();

                if (empty($shelfInfo)) {
                    return ['code' => 1, 'msg' => '无效货架，请重试', 'data' => ''];
                }

                $shelfLocationInfo = StorageShelfLocationModel::where('shelf_id', $value['shelf_id'])
                    ->where('shelf_location_id', $value['shelf_location_id'])->first();

                if (empty($shelfLocationInfo)) {
                    return ['code' => 1, 'msg' => '无效库位，请重试', 'data' => ''];
                }
            }

            if (empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`' . $value['warehouse'] . '`不存在', 'data' => ''];
            }

            if (empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '商品`' . $value['name'] . '-' . $value['type_name'] . '`不存在', 'data' => ''];
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            if (empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'shelf_id' => $shelfInfo['id'],
                    'shelf_location_id' => $shelfLocationInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'serial_number' => $value['serial_number'],
                    'is_use_serial' => $materielTypeInfo['is_use_serial'],
                    'main_id' => $mainId,
                    'in_storage_time' => time()
                ];
            } else {
                $instorageNumsData[] = [
                    'id' => $storageManageInfo['id'],//库存主键id
                    'in_storage_num' => $value['num'],//入库数量
                    'cost' => $storageManageInfo['materiel_mean_cost'],
                    'materiel_type_id' => $materielTypeInfo['id'],//物料id
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'storage_id' => $storageInfo['id'],
                    'shelf_id' => $shelfInfo['id'],
                    'shelf_location_id' => $shelfLocationInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类主键名称
                    'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                    'materiel_class_no' => $materielTypeInfo['class_no'],//物料二级分类编号
                    'serial_number' => $value['serial_number'],
                    'is_use_serial' => $materielTypeInfo['is_use_serial'],
                ];
            }
        }

        unset($value);

        DB::beginTransaction();
        try {
            if (!empty($instorageNumsData)) {
                //更新库存总数
                foreach ($instorageNumsData as $key => $value) {
                    StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num +' . $value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num +' . $value['in_storage_num']),
                            'delete_flag' => 0
                        ]);
                    MessageService::sendInSms(
                        '',
                        $value['materiel_name'],
                        $value['type_name'],
                        $value['storage_id'],
                        $value['storage_name'],
                        $datas = ['user_id' => $userId, 'main_id' => $mainId],
                        $value['in_storage_num'],
                        $value['in_storage_num']
                    );

                    $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    } while (!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );

                    LogInstorageModel::insert([
                        'curr_storage_manage_id' => $value['id'],
                        'materiel_type_id' => $value['materiel_type_id'],//物料id
                        'batch_id' => $batchId,//物料id
                        'materiel_name' => $value['materiel_name'],//物料名称
                        'type_name' => $value['type_name'],//物料型号
                        'materiel_no' => $value['materiel_no'],//物料编号
                        'materiel_class_id' => $value['materiel_class_id'],//物料二级分类主键名称
                        'materiel_class_name' => $value['materiel_class_name'],//物料二级分类名称
                        'materiel_class_no' => $value['materiel_class_no'],//物料二级分类编号
                        'type' => 0,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                        'storage_id' => $value['id'],//仓库主键id
                        'storage_name' => $value['storage_name'],//仓库名
                        'storage_address' => $value['storage_address'],//仓库地址
                        'last_storage_id' => 0,//调拨前所在仓库id
                        'operate_num' => $value['in_storage_num'],//操作数量
                        'last_storage_num' => 0,//操作前库存数
                        'materiel_mean_cost' => empty($storageManageInfo) ? 0 : $storageManageInfo['materiel_mean_cost'],//物料均价
                        'next_storage_num' => $value['in_storage_num'],//操作后库存数
                        'all_id_type' => $data['all_id_type'],//单据类型;0:无;1:报溢;2:退货;3:采购;
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'shelf_id' => $value['id'],
                        'serial_number' => isset($value['serial_number']) ? $value['serial_number'] : '',
                        'location_id' => $value['id'],
                        'all_id' => $data['all_id'],//单据id
                        'user_id' => $userId,//操作人用户id
                        'main_id' => $mainId,//主账号id
                        'remark' => empty($data['remark']) ? '' : $data['remark'],
                        'created_at' => time(),
                    ]);
                }
            }

            if (!empty($arr)) {
                foreach ($arr as $v) {
                    MessageService::sendInSms(
                        '',
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['storage_id'],
                        $v['storage_name'],
                        $datas = ['user_id' => $userId, 'main_id' => $mainId],
                        $v['in_storage_num'],
                        $v['in_storage_num']
                    );

                    $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    } while (!empty($checkBatchNo));

                    $insertId = StorageManageModel::insertGetId([
                        'materiel_class_id' => $v['materiel_class_id'],
                        'materiel_class_name' => $v['materiel_class_name'],
                        'materiel_class_no' => $v['materiel_class_no'],
                        'type_id' => $v['type_id'],
                        'materiel_name' => $v['materiel_name'],
                        'type_name' => $v['type_name'],
                        'materiel_no' => $v['materiel_no'],
                        'storage_id' => $v['storage_id'],
                        'storage_name' => $v['storage_name'],
                        'storage_address' => $v['storage_address'],
                        'in_storage_num' => $v['in_storage_num'],
                        'virtual_storage_num' => $v['in_storage_num'],
                        'shelf_id' => $v['id'],
                        'location_id' => $v['id'],
                        'main_id' => $mainId,
                        'in_storage_time' => time()
                    ]);

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $insertId,
                        0,
                        $v['in_storage_num'],
                        0,
                        $mainId
                    );

                    //生成入库操作记录
                    LogInstorageModel::insert([
                        'curr_storage_manage_id' => $insertId,
                        'materiel_type_id' => $v['type_id'],//物料id
                        'batch_id' => $batchId,//物料id
                        'materiel_name' => $v['materiel_name'],//物料名称
                        'type_name' => $v['type_name'],//物料型号
                        'materiel_no' => $v['materiel_no'],//物料编号
                        'materiel_class_id' => $v['materiel_class_id'],//物料二级分类主键名称
                        'materiel_class_name' => $v['materiel_class_name'],//物料二级分类名称
                        'materiel_class_no' => $v['materiel_class_no'],//物料二级分类编号
                        'type' => 0,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                        'storage_id' => $v['storage_id'],//仓库主键id
                        'storage_name' => $v['storage_name'],//仓库名
                        'storage_address' => $v['storage_address'],//仓库地址
                        'last_storage_id' => 0,//调拨前所在仓库id
                        'operate_num' => $v['in_storage_num'],//操作数量
                        'last_storage_num' => 0,//操作前库存数
                        'materiel_mean_cost' => 0,//物料均价
                        'next_storage_num' => $v['in_storage_num'],//操作后库存数
                        'all_id_type' => $data['all_id_type'],//单据类型;0:无;1:报溢;2:退货;3:采购;
                        'in_storage_time' => strtotime($data['in_storage_time']),//入库时间
                        'serial_number' => isset($v['serial_number']) ? $v['serial_number'] : '',
                        'shelf_id' => $v['id'],
                        'location_id' => $v['id'],
                        'all_id' => $data['all_id'],//单据id
                        'user_id' => $userId,//操作人用户id
                        'main_id' => $mainId,//主账号id
                        'remark' => empty($data['remark']) ? '' : $data['remark'],
                        'created_at' => time(),
                    ]);
                }
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '采购入库失败！', 'data' => ''];
        }
    }

    //批次列表
    static public function batchList($id)
    {
        return StorageManageModel::select(
            'a.id',
            'a.type_id',
            'b.type_name',
            'b.materiel_name',
            'b.materiel_no',
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->with('batchList', function ($query) {
                $query->select(
                    'storage_batch.id',
                    'batch_no',
                    'storage_manage_id',
                    'batch_num',
                    'batch_left_num',
                    'batch_cost',
                    'purchase_no',
                    'expiration_date',
                    'inspector',
                    'production_time',
                    'delivery_time',
                    'binding_supplier',
                    'warning_time',
                    'production_order_number',
                    'external_order_number',
                    'name as supplier_customer_name',
                    'd.username',
                    'd.nickname',
                    'storage_batch.upload_credentials_img'
                )->leftJoin('materiel as b', 'b.id', '=', 'storage_batch.materiel_id')
                    ->leftJoin('supplier_customer as c', 'c.id', '=', 'storage_batch.binding_supplier')
                    ->leftJoin('admin as d', 'd.id', '=', 'storage_batch.inspector');
            })
            ->where('a.id', $id)
            ->first()->toArray();
    }

    static public function batchMaterielInfo($id)
    {
        return StorageBatchModel::select(
            'a.id',
            'b.type_id',
            'a.batch_no',
            'a.batch_num',
            'a.batch_left_num',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.final_money',
            'd.supplier_name',
            'e.storage_name',
            'a.inspector',
            'a.binding_supplier',
            'a.production_order_number',
            'a.external_order_number',
            'a.expiration_date',
            'a.warning_time',
            'a.production_time',
            'a.upload_credentials_img',
            'a.delivery_time',
            'c.length',
            'c.width',
            'c.height',
            'c.weight',
            'a.created_at',
            'c.executive_standard',
            'c.texture',
            'c.materiel_unit',
            'b.in_storage_time',
            'c.bar_code',
            'name as supplier_customer_name',
            'phone as supplier_phone',
            'address as supplier_address',
            'company_type',
            'g.username',
            'g.nickname',
            'c.remark',
            DB::raw('SUM(batch_num * selling_price) as total_money')
        )->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
            ->leftJoin('materiel as d', 'd.id', 'a.materiel_id')
            ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
            ->leftJoin('supplier_customer as f', 'f.id', '=', 'a.binding_supplier')
            ->leftJoin('admin as g', 'g.id', '=', 'a.inspector')
            ->where('a.id', $id)
            ->first();
    }

    //识别条码
    static public function readBatchNo($data)
    {
        $subBatchInfo = substr($data['batch_no'], -1, 1);

        if ($subBatchInfo == 'a') {
            $result = self::readSellPackage($data['batch_no']);

            if (empty($result)) {
                return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
            }
            $result['type'] = 1;
        } else {
            $result = self::readMateriel($data['batch_no']);
            if (empty($result)) {
                return ['code' => 1, 'msg' => '暂无条码信息', 'data' => ''];
            }
            $result['type'] = 0;
        }

        return ['code' => 0, 'msg' => 'success', 'data' => $result];
    }

    static private function readSellPackage($batchNo)
    {
        return SellPackageDetailModel::select(
            'a.id',
            'package_no',
            'package_id',
            'package_name',
            'num',
            'price'
        )
            ->from('sell_package_detail as a')
            ->leftJoin('package as b', 'b.id', '=', 'a.package_id')
            ->with('packageContent', function ($query) {
                $query->select(
                    'b.in_storage_num',
                    'sell_package_content.materiel_type_id',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'c.id as storage_id',
                    'c.storage_name',
                    'sell_package_content.package_detail_id',
                    'sell_package_content.storage_manage_id',
                    'sell_package_content.num',
                    'sell_package_content.total_num'
                )
                    ->leftJoin('materiel_type as a', 'a.id', '=', 'sell_package_content.materiel_type_id')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'sell_package_content.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'sell_package_content.storage_id');
            })
            ->where('package_no', $batchNo)
            ->first();
    }

    //商品批次信息
    static private function readMateriel($batchNo)
    {
        return StorageBatchModel::select(
            'a.id as batch_id',
            'batch_no',
            'batch_num',
            'batch_left_num',
            'b.in_storage_num',
            'b.type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_img',
            'c.materiel_no',
            'd.id as storage_id',
            'd.storage_name',
            'a.storage_manage_id',
            'f.price as sell_price'
        )
            ->from('storage_batch as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'b.type_id', '=', 'c.id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('sell_goods_detail_batch as e', 'e.storage_batch_id', '=', 'a.id')
            ->leftJoin('sell_goods_detail as f', 'f.id', '=', 'e.sell_goods_detail_id')
            ->where('batch_no', $batchNo)
            ->first();
    }

    //商品库存批次列表
    static public function materielBatchList($typeId, $sellId, $type, $data)
    {
        $result = StorageManageModel::materielBatchList($typeId, $data);
//        if($type == 0) {
//            $sellGoodsBatchInfo = SellGoodsDetailModel::getBatchInfo($sellId);
//
//            if(empty($sellGoodsBatchInfo)) {
//                foreach($result as &$value) {
//                    $value['is_used'] = 0;
//                }
//            }
//            else {
//                foreach($result as &$value) {
//                    foreach($sellGoodsBatchInfo as $val) {
//                        if($value['materiel_type_id'] == $val['materiel_type_id']) {
//                            $value['is_used'] = 1;
//                        }
//                        else {
//                            $value['is_used'] = 0;
//                        }
//                    }
//                }
//            }
//        }
//        else {
//            $sellPackageBatchInfo = SellPackageContentModel::getBatchInfo($sellId, $data);
//
//            if(empty($sellPackageBatchInfo)) {
//                foreach($result as &$value) {
//                    $value['is_used'] = 0;
//                }
//            }
//            else {
//                foreach($result as &$value) {
//                    foreach($sellPackageBatchInfo as $val) {
//                        if($value['materiel_type_id'] == $val['materiel_type_id']) {
//                            $value['is_used'] = 1;
//                        }
//                        else {
//                            $value['is_used'] = 0;
//                        }
//                    }
//                }
//            }
//        }

        return $result;
    }

    static public function fastOutStorage($data, $formType)
    {
        $batchSign = substr($data['batch_no'], 0, strlen($data['batch_title']));
        $batchNoTag = substr($data['batch_no'], -1, 1);
        $condition = [];
        $info = '';
        if ($data['code_type'] != 1) {
            if ($data['code_type'] == 0) {
                $condition['id'] = substr($data['batch_no'], 5, strlen($data['batch_no']) - 1);
            } elseif ($data['code_type'] == 3) {
                if (strpos($data['batch_no'], 'SMYCYJ') !== false) {
                    $code = explode('SMYCYJ', $data['batch_no']);
                    $condition['inventory_code'] = $code;
                } else {
                    $condition['bar_code'] = $data['batch_no'];
                }
            }
            $info = MaterielTypeModel::where($condition)
                ->where([
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])->first();

            if (!empty($info)) {
                if (!empty($info['is_use_serial'])) {
                    return ['code' => 1, 'msg' => '您开启了序列号，请选择序列号出库！', 'data' => ''];
                }
            } else {
                $result = ['code' => 1, 'msg' => '商品信息，不存在!', 'data' => ''];
            }
        } else {
            $info = SerialNumberModel::query()
                ->select('materiel_name')
                ->from('serial_number as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.goods_id')
                ->where([
                    'main_id' => $data['main_id'],
                    'a.delete_flag' => 0,
                    'b.delete_flag' => 0,
                    'b.id' => $data['goods_id'],
                    'b.serial_no' => $data['batch_no']
                ])->first();
        }
        //仓库信息
        $storageInfo = StorageModel::where([
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();
        //入库仓库信息
        /*$storageInfo = StorageModel::query()
            ->select(
                'a.id as storage_id',
                'b.id as shelf_id',
                'c.id as location_id',
                'storage_name',
                'shelf_name',
                'location_name',
                'storage_address',
            )->from('storage as a')
            ->leftJoin('storage_shelf as b','b.storage_id','=','a.id')
            ->leftJoin('storage_shelf_location as c','c.shelf_id','=','b.id')
            ->where([
                'a.id' => $data['storage_id'],
                'b.id' => $data['shelf_id'],
                'c.id' => $data['location_id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
                'b.status' => 1,
                'c.status' => 1
            ])->first();*/

        if (empty($storageInfo)) {
            return ['code' => 1, 'msg' => '您选择的仓库，不存在！', 'data' => ''];
        }
        $result = [];
        if ($data['code_type'] == 0 && strpos($data['batch_no'], 'smycg') !== false) {//物料商品id
            $data['batch_no'] = substr($data['batch_no'], 5, strlen($data['batch_no']) - 1);
            $result = self::goodsOut($data, $formType);
        } elseif ($data['code_type'] == 2) {//商品批次號
            $result = ['code' => 1, 'msg' => '批次号出库，正在维护中！', 'data' => ''];
            //$result = self::materielOut($data, $formType);
        } elseif ($batchSign . 'a' == $data['batch_title'] . $batchNoTag) {//套餐批次號
            $result = ['code' => 1, 'msg' => '批次号出库，正在维护中！', 'data' => ''];
            //$result = self::packageFastOut($data);
        } elseif ($data['code_type'] == 1) {//序列号
            $result = [];
            if (!empty($data['goods_id']) && !empty($data['batch_no'])) {
                $result = self::serialMaterielOut($data, $formType);
            } else {
                $result = ['code' => 1, 'msg' => '序列号商品信息，不存在。', 'data' => ''];
            }
        } elseif ($data['code_type'] == 3) {//条形码
            $result = [];

            if (!empty($data['batch_no'])) {
                $result = self::barCodeMaterielOut($data, $formType);
            } else {
                $result = ['code' => 1, 'msg' => '条形码商品信息，不存在。', 'data' => ''];
            }
        }

        CommonService::operateResult($data['user_id'], $result, $data['time']);
        if (isset($result['code'])) {
            if ($result['code'] == 0) {
                if (!empty($info)) {
                    return ['code' => 0, 'msg' => 'success', 'data' => $info['materiel_name'] . '，出库成功！'];
                } else {
                    return ['code' => 0, 'msg' => 'success', '出库成功！'];
                }
            }
        }
        return $result;
    }

    static public function materielOut($data, $formType)
    {
        if (empty($data['sell_id'])) {
            $result = self::materielDirectlyFastOut($data);
        } else {
            switch ($formType) {
                case 0:
                    $result = self::materielSellFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    static public function goodsOut($data, $formType)
    {
        if (empty($data['sell_id'])) {
            $result = self::goodsDirectlyFastOut($data);
        } else {
            switch ($formType) {
                case 0:
                    $result = self::goodsSellFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    /**
     * 序列号识别物料出库
     */
    static public function serialMaterielOut($data, $formType)
    {
        if (empty($data['sell_id'])) {

            $result = self::serialMaterielDirectlyFastOut($data);
        } else {

            switch ($formType) {
                case 0:
                    $result = self::serialMaterielSellFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    static public function barCodeMaterielOut($data, $formType)
    {
        if (empty($data['sell_id'])) {
            $result = self::goodsBarCodeFastOut($data);
        } else {
            switch ($formType) {
                case 0:
                    $result = self::sellGoodsBarCodeFastOut($data);
                    break;
                case 1:
                    break;
                case 2:
                    break;
            }
        }

        return $result;
    }

    static public function fastOutStorage1($data, $formType)
    {
        if (isset($data['sell_id'])) {
            $sellInfo = SellModel::where('id', $data['sell_id'])->first();
            if ($sellInfo['repeal_status']) {
                return [
                    'code' => 1,
                    'msg' => '目标销售单已撤销',
                    'data' => ''
                ];
            }

            if ($sellInfo['delete_flag']) {
                return [
                    'code' => 1,
                    'msg' => '目标销售单已删除',
                    'data' => ''
                ];
            }

            if ($sellInfo['out_status'] == 2) {
                return [
                    'code' => 1,
                    'msg' => 'success',
                    'data' => [
                        'is_finished' => 1
                    ]
                ];
            }
        }

        $batchSign = substr($data['batch_no'], 0, strlen($data['batch_title']));
        $batchNoTag = substr($data['batch_no'], -1, 1);

        if ($batchSign . '0' == $data['batch_title'] . $batchNoTag) {//商品批次號
            $result = self::materielFastOut($data);
        } else if ($batchSign . 'a' == $data['batch_title'] . $batchNoTag) {//套餐批次號
            $result = self::packageFastOut($data);
        } else {//序列號
            $result = self::serialFastOut($data);
        }

        DB::beginTransaction();

        try {
            switch ($formType) {
                case 0:
                    self::updateSellStatus($data);
                    break;
            }

            DB::commit();
            return $result;
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('快速出库，出库状态异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '快速出库异常', 'data' => ''];
        }
    }

    static private function updateSellStatus()
    {
        if (isset($data['sell_id'])) {
            //更新销售入库状态
            SellModel::where('id', $data['sell_id'])->update(['out_status' => 1, 'prepare_out_status' => 0]);

            $sellGoodsInfo = SellGoodsDetailModel::where('sell_id', $data['sell_id'])
                ->whereRaw('num > out_num')
                ->first();

            $sellPackageInfo = SellPackageDetailModel::where('sell_id', $data['sell_id'])
                ->whereRaw('num > out_num')
                ->first();

            if (empty($sellGoodsInfo) && empty($sellPackageInfo)) {
                SellModel::where('id', $data['sell_id'])->update(['out_status' => 2, 'prepare_out_status' => 0]);//全部完成更新状态
                CheckModel::where(['main_id' => $data['main_id'], 'type' => 2, 'all_id' => $data['sell_id']])
                    ->update(['status' => 1, 'out_in_status' => 0]);
            } else {
                CheckModel::where(['main_id' => $data['main_id'], 'type' => 2, 'all_id' => $data['sell_id']])
                    ->update(['out_in_status' => 1]);
            }
        }
    }

    static private function packageFastOut($data)
    {
        DB::beginTransaction();
        try {
            $sellPackageBatchInfo = SellPackageDetailModel::select(
                'a.id',
                'a.package_id',
                'c.package_name',
                'out_num',
                'a.num'
            )
                ->from('sell_package_detail as a')
                ->leftJoin('package as c', 'c.id', '=', 'a.package_id')
                ->where('a.sell_id', $data['sell_id'])
                ->where('package_no', $data['batch_no'])
                ->first();

            if (empty($sellPackageBatchInfo)) {
                return [
                    'code' => 1,
                    'msg' => '套餐批次不存在，请重试',
                    'data' => ''
                ];
            }

            if ($sellPackageBatchInfo['num'] == $sellPackageBatchInfo['out_num']) {
                return ['code' => 1, 'msg' => '该套餐已全部出库', 'data' => ''];
            }

            $logPackageBasicInfo = [
                'package_id' => $sellPackageBatchInfo['package_id'],
                'package_name' => $sellPackageBatchInfo['package_name'],
                'num' => 1,
                'all_id_type' => 2,
                'all_id' => $data['sell_id'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'created_at' => time()
            ];

            $logId = LogPackageModel::insertGetId($logPackageBasicInfo);

            if (($sellPackageBatchInfo['num'] - $sellPackageBatchInfo['out_num']) < 1) {
                return [
                    'code' => 1,
                    'msg' => '可出库套餐数不足',
                    'data' => ''
                ];
            }

            if ($data['out_way']) {

                //获取销售单套餐内容
                $sellPackageContent = SellPackageContentModel::select(
                    'a.id',
                    'num'
                )
                    ->from('sell_package_content as a')
                    ->with('packageBatchInfo', function ($query) {
                        $query->select(
                            'a.id',
                            'sell_package_batch.storage_manage_id',
                            'sell_package_content_id',
                            'num',
                            'b.storage_id',
                            'c.storage_name',
                            'c.storage_address',
                            'b.type_id',
                            'd.materiel_name',
                            'd.type_name',
                            'd.materiel_no',
                            'in_storage_num',
                            'materiel_mean_cost',
                            'e.id as materiel_class_id',
                            'e.class_name',
                            'e.class_no',
                            'alert_num',
                            'in_storage_num',
                            'batch_left_num'
                        )
                            ->leftJoin('storage_batch as a', 'sell_package_batch.storage_batch_id', '=', 'a.id')
                            ->leftJoin('storage_manage as b', 'sell_package_batch.storage_manage_id', '=', 'b.id')
                            ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                            ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                            ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id');
                    })
                    ->where('package_detail_id', $sellPackageBatchInfo['id'])
                    ->get()->toArray();

                $arr = [];
                $logPackageContentData = [];
                foreach ($sellPackageContent as $value) {
                    $totalNum = 0;
                    foreach ($value['package_batch_info'] as $val) {
                        $totalNum += $val['batch_left_num'];
                        MessageService::sendAlertSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $val['alert_num'],
                            $data,
                            $val['storage_id'],
                            $val['storage_name'],
                            $value['num']
                        );

                        MessageService::sendShortSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $data,
                            $val['storage_id'],
                            $val['storage_name']
                        );

                        MessageService::sendOutSms(
                            $val['materiel_name'],
                            $val['type_name'],
                            $val['in_storage_num'] - $value['num'],
                            $val['storage_name'],
                            $value['num'],
                            $data,
                            $val['storage_id'],
                            $val['alert_num']
                        );

                        $logPackageContentData[] = [
                            'log_package_id' => $logId,
                            'package_id' => $sellPackageBatchInfo['package_id'],
                            'storage_id' => $val['storage_id'],
                            'storage_name' => $val['storage_name'],
                            'storage_address' => $val['storage_address'],
                            'materiel_class_id' => $val['materiel_class_id'],
                            'materiel_class_name' => $val['class_name'],
                            'materiel_class_no' => $val['class_name'],
                            'materiel_type_id' => $val['type_id'],
                            'materiel_name' => $val['materiel_name'],
                            'type_name' => $val['type_name'],
                            'materiel_no' => $val['materiel_no'],
                            'operate_num' => $value['num'],
                            'out_storage_manage_id' => $val['storage_manage_id'],
                            'last_storage_num' => $val['in_storage_num'],
                            'next_storage_num' => $val['in_storage_num'] - $value['num'],
                            'all_id_type' => 4,
                            'all_id' => $data['sell_id'],
                            'user_id' => $data['user_id'],
                            'main_id' => $data['main_id'],
                            'storage_batch_id' => $val['id'],
                            'created_at' => time()
                        ];

                        if ($val['in_storage_num'] < $value['num']) {
                            return [
                                'code' => 1,
                                'msg' => '库存不足，无法出库',
                                'data' => ''
                            ];
                        }

                        StorageManageModel::where('id', $val['storage_manage_id'])
                            ->update([
                                'in_storage_num' => DB::raw("in_storage_num -" . $value['num']),
                                'virtual_storage_num' => DB::raw("virtual_storage_num -" . $value['num'])
                            ]);

                        StorageBatchModel::where('id', $val['id'])
                            ->decrement('batch_left_num', $value['num']);
                    }

                    if ($totalNum < $value['num']) {
                        return [
                            'code' => 1,
                            'msg' => '批次库存数量不足，无法出库',
                            'data' => ''
                        ];
                    }
                }
                LogPackageContentModel::insert($logPackageContentData);
            } else {
                //获取销售单套餐内容
                $sellPackageContent = SellPackageContentModel::select(
                    'a.id',
                    'storage_manage_id',
                    'num',
                    'b.storage_id',
                    'c.storage_name',
                    'c.storage_address',
                    'b.type_id',
                    'd.materiel_name',
                    'd.type_name',
                    'd.materiel_no',
                    'in_storage_num',
                    'materiel_mean_cost',
                    'e.id as materiel_class_id',
                    'e.class_name',
                    'e.class_no',
                    'alert_num'
                )
                    ->from('sell_package_content as a')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                    ->where('package_detail_id', $sellPackageBatchInfo['id'])
                    ->get()->toArray();

                $arr = [];
                $logPackageContentData = [];
                foreach ($sellPackageContent as $value) {
                    if ($value['num'] > $value['in_storage_num']) {
                        return [
                            'code' => 1,
                            'msg' => '库存数不足，无法完成出库',
                            'data' => ''
                        ];
                    }

                    $arr[] = [
                        'storage_manage_id' => $value['storage_manage_id'],
                        'operate_num' => $value['num'],
                        'in_storage_num' => $value['in_storage_num'],
                        'alert_num' => $value['in_storage_num'],
                        'storage_id' => $value['storage_id'],
                        'storage_name' => $value['storage_name'],
                        'storage_address' => $value['storage_address'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                    ];

                    $logPackageContentData[] = [
                        'log_package_id' => $logId,
                        'package_id' => $sellPackageBatchInfo['package_id'],
                        'storage_id' => $value['storage_id'],
                        'storage_name' => $value['storage_name'],
                        'storage_address' => $value['storage_address'],
                        'materiel_class_id' => $value['materiel_class_id'],
                        'materiel_class_name' => $value['class_name'],
                        'materiel_class_no' => $value['class_name'],
                        'materiel_type_id' => $value['type_id'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                        'materiel_no' => $value['materiel_no'],
                        'operate_num' => $value['num'],
                        'out_storage_manage_id' => $value['storage_manage_id'],
                        'last_storage_num' => $value['in_storage_num'],
                        'next_storage_num' => $value['in_storage_num'] - $value['num'],
                        'all_id_type' => 4,
                        'all_id' => $data['sell_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'created_at' => time()
                    ];
                }

                LogPackageContentModel::insert($logPackageContentData);

                foreach ($arr as $v) {
                    MessageService::sendAlertSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $v['alert_num'],
                        $data,
                        $v['storage_id'],
                        $v['storage_name'],
                        $v['operate_num']
                    );

                    MessageService::sendShortSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $data,
                        $v['storage_id'],
                        $v['storage_name']
                    );

                    MessageService::sendOutSms(
                        $v['materiel_name'],
                        $v['type_name'],
                        $v['in_storage_num'] - $v['operate_num'],
                        $v['storage_name'],
                        $v['operate_num'],
                        $data,
                        $v['storage_id'],
                        $v['alert_num']
                    );

                    StorageManageModel::where('id', $v['storage_manage_id'])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num -" . $v['operate_num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num -" . $v['operate_num'])
                        ]);
                }
            }

            SellPackageDetailModel::where('id', $sellPackageBatchInfo['id'])
                ->increment('out_num', 1);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('销售单套餐快速出库异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '销售单套餐快速出库异常', 'data' => ''];
        }
    }

    static private function materielFastOut($data)
    {
        if (isset($data['sell_id'])) {
            return self::materielSellFastOut($data);
        } else {
            return self::materielDirectlyFastOut($data);
        }
    }

    static private function materielDirectlyFastOut($data)
    {
        DB::beginTransaction();

        try {

            $storageBatchInfo = StorageBatchModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'c.materiel_name',
                'c.type_name',
                'c.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'b.virtual_storage_num',
                'b.alert_num'
            )
                ->from('storage_batch as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('batch_no', $data['batch_no'])->first();

            if (empty($storageBatchInfo)) {

                return ['code' => 1, 'msg' => '批次不存在，无法出库', 'data' => ''];
            }

            if ($storageBatchInfo['batch_left_num'] <= 0) {

                return ['code' => 1, 'msg' => '库存批次数量不足,无法出库', 'data' => ''];
            }

            if ($storageBatchInfo['in_storage_num'] <= 0) {

                return ['code' => 1, 'msg' => '库存数量不足，无法出库', 'data' => ''];
            }

            if ($storageBatchInfo['virtual_storage_num'] <= 0) {

                return ['code' => 1, 'msg' => '商品虚拟库存数量不足', 'data' => ''];
            }

            $logOutInfo = [
                'type' => 2,
                'storage_batch_id' => $storageBatchInfo['batch_id'],
                'storage_id' => $storageBatchInfo['storage_id'],
                'storage_name' => $storageBatchInfo['storage_name'],
                'storage_address' => $storageBatchInfo['storage_address'],
                'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                'materiel_class_name' => $storageBatchInfo['class_name'],
                'materiel_class_no' => $storageBatchInfo['class_no'],
                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                'materiel_name' => $storageBatchInfo['materiel_name'],
                'type_name' => $storageBatchInfo['type_name'],
                'materiel_no' => $storageBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $storageBatchInfo['in_storage_num'],
                'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                'sell_price' => $storageBatchInfo['materiel_mean_cost'],
                'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                'out_storage_time' => time(),
                'created_at' => time()
            ];

            MessageService::sendAlertSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['alert_num'],
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
                1
            );

            MessageService::sendShortSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name']
            );

            MessageService::sendOutSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['storage_name'],
                1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['alert_num']
            );

            LogOutStorageModel::insert($logOutInfo);

            StorageBatchModel::where('id', $storageBatchInfo['batch_id'])
                ->decrement('batch_left_num', 1);

            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1")
                ]);

            /* SellGoodsDetailModel::where('id',$storageBatchInfo['sell_goods_detail_id'])
                ->increment('out_num', 1); */

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('商品直接出库异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品直接出库异常，请重试', 'data' => ''];
        }
    }

    static private function goodsDirectlyFastOut($data)
    {
        DB::beginTransaction();
        try {
            $storageBatchInfo = materielTypeModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'a.materiel_name',
                'a.type_name',
                'a.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'b.virtual_storage_num',
                'b.alert_num',
                'a.is_use_serial',
                'a.selling_price'
            )
                ->from('materiel_type as a')
                ->leftJoin('storage_manage as b', 'b.type_id', '=', 'a.id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'a.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where('a.id', $data['batch_no'])
                ->where('a.main_id', $data['main_id'])
                ->where('b.storage_id', $data['storage_id'])
                /*  ->where('b.shelf_id',$data['shelf_id'])
                ->where('b.location_id',$data['location_id'])*/
                ->where('a.delete_flag', 0)
                ->where('b.delete_flag', 0)
                ->first();

            if (empty($storageBatchInfo)) {
                return ['code' => 1, 'msg' => '无商品库存信息，不能出库', 'data' => ''];
            }
            if (!OperMainAccountModel::query()
                ->where([
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])->exists()) {
                if ($storageBatchInfo['in_storage_num'] <= 0) {
                    return ['code' => 1, 'msg' => '库存数量不足，不能出库', 'data' => ''];
                }
            }
            if ($storageBatchInfo['is_use_serial'] == 1) {
                return ['code' => 1, 'msg' => '您开启了序列号，请选择序列号出库！', 'data' => ''];
            }
            /*if($storageBatchInfo['virtual_storage_num'] <=0) {
                    return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
                }*/
            //库存数达到预警
//                    $sortFlag = 0;
//                if($storageBatchInfo['in_storage_num']-1 <= $storageBatchInfo['alert_num']) {
//                    $sortFlag = 1;
//                }

            $logOutInfo = [
                'type' => 4,
                'storage_batch_id' => "",
                'storage_id' => $storageBatchInfo['storage_id'],
                'storage_name' => $storageBatchInfo['storage_name'],
                'storage_address' => $storageBatchInfo['storage_address'],
                'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                'materiel_class_name' => $storageBatchInfo['class_name'],
                'materiel_class_no' => $storageBatchInfo['class_no'],
                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                'materiel_name' => $storageBatchInfo['materiel_name'],
                'type_name' => $storageBatchInfo['type_name'],
                'materiel_no' => $storageBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $storageBatchInfo['in_storage_num'],
                'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                'sell_price' => $storageBatchInfo['selling_price'],
                'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                /*  'shelf_id' => $data['shelf_id'],
                    'location_id' => $data['location_id'],*/
                'out_storage_time' => $data['time'],
                'created_at' => $data['time']
            ];

            MessageService::sendAlertSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['alert_num'],
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
                1
            );

            MessageService::sendShortSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $data,
                $storageBatchInfo['storage_name'],
                $storageBatchInfo['storage_id'],
            );

            MessageService::sendOutSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['storage_name'],
                1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['alert_num']
            );

            LogOutStorageModel::insert($logOutInfo);

            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    //'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
//                    'sort_flag'=>$sortFlag
                ]);

            MaterielTypeModel::where(['id' => $storageBatchInfo['materiel_type_id']])
                ->update(['price_last' => $storageBatchInfo['selling_price']]);

            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('商品ID扫码出库异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品ID扫码,出库失败！', 'data' => ''];
        }

    }

    static private function goodsBarCodeFastOut($data)
    {
        DB::beginTransaction();
        try {
            $storageBatchInfo = materielTypeModel::select(
                'b.id as storage_manage_id',
                'b.type_id as materiel_type_id',
                'a.materiel_name',
                'a.type_name',
                'a.materiel_no',
                'd.id as materiel_class_id',
                'd.class_name',
                'd.class_no',
                'e.id as storage_id',
                'e.storage_name',
                'e.storage_address',
                'in_storage_num',
                'materiel_mean_cost',
                'b.virtual_storage_num',
                'b.alert_num',
                'a.is_use_serial',
                'a.selling_price'
            )
                ->from('materiel_type as a')
                ->leftJoin('storage_manage as b', 'b.type_id', '=', 'a.id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'a.materiel_class_id')
                ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
                ->where(function ($query) use ($data) {
                    if (strpos($data['batch_no'], 'SMYCYJ') != false) {
                        $code = explode('SMYCYJ', $data['batch_no'])[0];
                        $query->where('a.inventory_code', $code);
                    } else {
                        $query->where('a.bar_code', $data['batch_no']);
                    }
                })
                ->where('a.main_id', $data['main_id'])
                ->where('b.storage_id', $data['storage_id'])
                /*->where('b.shelf_id',$data['shelf_id'])
                ->where('b.location_id',$data['location_id'])*/
                ->where('a.delete_flag', 0)
                ->where('b.delete_flag', 0)
                ->first();
            if (empty($storageBatchInfo)) {
                return ['code' => 1, 'msg' => '无商品库存信息！', 'data' => ''];
            }
            if ($storageBatchInfo['is_use_serial'] == 1) {
                return ['code' => 1, 'msg' => '库存数量不足，无法出库', 'data' => ''];
            }
            if (!OperMainAccountModel::query()
                ->where([
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])->exists()) {
                if ($storageBatchInfo['in_storage_num'] <= 0) {
                    return ['code' => 1, 'msg' => '库存数量不足，无法出库', 'data' => ''];
                }
            }
            /*  if($storageBatchInfo['virtual_storage_num'] <=0) {
                    return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
                }*/
            //库存数达到预警
//                $sortFlag = 0;
//                if($storageBatchInfo['in_storage_num']-1 <= $storageBatchInfo['alert_num']) {
//                    $sortFlag = 1;
//                }
            $logOutInfo = [
                'type' => 4,
                'storage_batch_id' => "",
                'storage_id' => $storageBatchInfo['storage_id'],
                'storage_name' => $storageBatchInfo['storage_name'],
                'storage_address' => $storageBatchInfo['storage_address'],
                'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
                'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
                'materiel_class_name' => $storageBatchInfo['class_name'],
                'materiel_class_no' => $storageBatchInfo['class_no'],
                'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
                'materiel_name' => $storageBatchInfo['materiel_name'],
                'type_name' => $storageBatchInfo['type_name'],
                'materiel_no' => $storageBatchInfo['materiel_no'],
                'operate_num' => 1,
                'last_storage_num' => $storageBatchInfo['in_storage_num'],
                'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
                'sell_price' => $storageBatchInfo['selling_price'],
                'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
                'user_id' => $data['user_id'],
                'main_id' => $data['main_id'],
                /* 'shelf_id' => $data['shelf_id'],
                    'location_id' => $data['location_id'],*/
                'out_storage_time' => time(),
                'created_at' => time()
            ];
            $logId = LogOutStorageModel::query()->insertGetId($logOutInfo);
            MessageService::sendAlertSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['alert_num'],
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
                1
            );

            MessageService::sendShortSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $data,
                $storageBatchInfo['storage_name'],
                $storageBatchInfo['storage_id']
            );

            MessageService::sendOutSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['storage_name'],
                1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['alert_num'],
                $logId
            );

            StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    //'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
//                    'sort_flag'=>$sortFlag
                ]);
            MaterielTypeModel::where(['id' => $storageBatchInfo['materiel_type_id']])->update(['price_last' => $storageBatchInfo['selling_price']]);
            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('条形码商品扫码出库异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }

    }

    static private function serialMaterielDirectlyFastOut($data)
    {
        $sInfo = SerialNumberModel::where([
            'serial_no' => $data['batch_no'],
            'goods_id' => $data['goods_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0
        ])->first();

        if (!empty($sInfo)) {
            if ($sInfo['status'] == 0) {
                return ['code' => 1, 'msg' => '序列号已使用,无法出库', 'data' => ''];
            }
            if (!empty($sInfo['parent_id'])) {
                return ['code' => 1, 'msg' => '该商品作为套餐中的套件使用,请整件出库', 'data' => ''];
            }
        } else {
            return ['code' => 1, 'msg' => '序列号商品不存在，无法出库', 'data' => ''];
        }

        $storageBatchInfo = SerialNumberModel::select(
            'b.id as storage_manage_id',
            'b.type_id as materiel_type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.id as materiel_class_id',
            'd.class_name',
            'd.class_no',
            'e.id as storage_id',
            'e.storage_name',
            'e.storage_address',
            'in_storage_num',
            'materiel_mean_cost',
            'a.status as serial_status',
            'b.virtual_storage_num',
            'b.alert_num',
            'c.selling_price',
            'c.is_product_materiel',
            'a.parent_id',
            'a.id as serial_id',
            'a.serial_no'
        )
            ->from('serial_number as a')
            ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'b.type_id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
            ->leftJoin('storage as e', 'e.id', '=', 'b.storage_id')
            ->where('c.id', $data['goods_id'])
            ->where('serial_no', $data['batch_no'])
            ->where('b.storage_id', $data['storage_id'])
            /* ->where('b.shelf_id',$data['shelf_id'])
                ->where('b.location_id',$data['location_id'])*/
            ->where('b.main_id', $data['main_id'])
            ->where('c.delete_flag', 0)
            ->where('b.delete_flag', 0)
            ->where('a.delete_flag', 0)
            ->first();
        if (empty($storageBatchInfo)) {
            return ['code' => 1, 'msg' => '序列号商品无库存信息，无法出库', 'data' => ''];
        }
        if (empty($storageBatchInfo['serial_no'])) {
            return ['code' => 1, 'msg' => '序列号商品不存在，无法出库', 'data' => ''];
        }
        if ($storageBatchInfo['serial_status'] == 0) {
            return ['code' => 1, 'msg' => '序列号已使用,无法出库', 'data' => ''];
        }
        if (!OperMainAccountModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->exists()) {
            if ($storageBatchInfo['in_storage_num'] <= 0) {
                return ['code' => 1, 'msg' => '库存数量不足，无法出库', 'data' => ''];
            }
        }
        /*    if($storageBatchInfo['virtual_storage_num'] <= 0) {
                    return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
                }*/
        //库存数达到预警
//                $sortFlag = 0;
//                if($storageBatchInfo['in_storage_num']-1 <= $storageBatchInfo['alert_num']) {
//                    $sortFlag = 1;
//                }
        $logOutInfo = [
            'type' => 4,
            'storage_id' => $storageBatchInfo['storage_id'],
            'storage_name' => $storageBatchInfo['storage_name'],
            'storage_address' => $storageBatchInfo['storage_address'],
            'curr_storage_manage_id' => $storageBatchInfo['storage_manage_id'],
            'materiel_class_id' => $storageBatchInfo['materiel_class_id'],
            'materiel_class_name' => $storageBatchInfo['class_name'],
            'materiel_class_no' => $storageBatchInfo['class_no'],
            'materiel_type_id' => $storageBatchInfo['materiel_type_id'],
            'materiel_name' => $storageBatchInfo['materiel_name'],
            'type_name' => $storageBatchInfo['type_name'],
            'materiel_no' => $storageBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $storageBatchInfo['in_storage_num'],
            'next_storage_num' => $storageBatchInfo['in_storage_num'] - 1,
            'sell_price' => $storageBatchInfo['selling_price'],
            'materiel_mean_cost' => $storageBatchInfo['materiel_mean_cost'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            /* 'shelf_id' => $data['shelf_id'],
                    'location_id' => $data['location_id'],*/
            'out_storage_time' => $data['time'],
            'created_at' => $data['time'],
            'serial_number' => $data['batch_no']
        ];

        DB::beginTransaction();
        try {
            MessageService::sendAlertSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['alert_num'],
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['storage_name'],
                1
            );

            MessageService::sendShortSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $data,
                $storageBatchInfo['storage_name'],
                $storageBatchInfo['storage_id'],
            );

            MessageService::sendOutSms(
                $storageBatchInfo['materiel_name'],
                $storageBatchInfo['type_name'],
                $storageBatchInfo['in_storage_num'] - 1,
                $storageBatchInfo['storage_name'],
                1,
                $data,
                $storageBatchInfo['storage_id'],
                $storageBatchInfo['alert_num']
            );

            $id = LogOutStorageModel::insert($logOutInfo);

            $bool = StorageManageModel::where('id', $storageBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    //'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
//                    'sort_flag'=>$sortFlag
                ]);

            SerialNumberModel::where([
                'delete_flag' => 0,
                'serial_no' => $storageBatchInfo['serial_no'],
                'goods_id' => $storageBatchInfo['materiel_type_id'],
                'storage_manage_id' => $storageBatchInfo['storage_manage_id']
            ])->update(['status' => 0]);

            if ($storageBatchInfo['is_product_materiel'] == 1 && empty($storageBatchInfo['parent_id'])) {

                if (!empty($storageBatchInfo['serial_id'])) {
                    SerialNumberModel::where([
                        'parent_id' => $storageBatchInfo['serial_id'],
                        'delete_flag' => 0
                    ])->update(['status' => 0]);
                }
            }
            MaterielTypeModel::where(['id' => $storageBatchInfo['materiel_type_id']])
                ->update(['price_last' => $storageBatchInfo['selling_price']]);
            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('序列号扫码，出库失败' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '序列号扫码,出库失败!', 'data' => ''];
        }
    }

    //销售单快速出库
    static private function materielSellFastOut($data)
    {
        if ($data['out_way']) {
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'b.id as sell_goods_batch_id',
                'a.materiel_type_id',
                'f.materiel_name',
                'f.type_name',
                'f.materiel_no',
                'a.num',
                'a.out_num',
                'b.num as batch_num',
                'b.rest_num',
                'storage_batch_id',
                'batch_left_num',
                'in_storage_num',
                'storage_id',
                'e.storage_name',
                'e.storage_address',
                'd.id as storage_manage_id',
                'f.materiel_class_id',
                'g.class_name',
                'g.class_no',
                'materiel_mean_cost',
                'alert_num',
                'c.id as batch_id',
                'a.price',
                'd.virtual_storage_num'
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('sell_goods_detail_batch as b', 'b.sell_goods_detail_id', '=', 'a.id')
                ->leftJoin('storage_batch as c', 'c.id', '=', 'b.storage_batch_id')
                ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
                ->leftJoin('storage as e', 'e.id', '=', 'd.storage_id')
                ->leftJoin('materiel_type as f', 'f.id', '=', 'd.type_id')
                ->leftJoin('materiel_class as g', 'g.id', '=', 'f.materiel_class_id')
                ->where('c.batch_no', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->orderBy('b.rest_num', 'desc')
                ->first();

            //商品已设置批次号
            if (!empty($sellGoodsBatchInfo)) {
                if ($sellGoodsBatchInfo['num'] == $sellGoodsBatchInfo['out_num']) {
                    return [
                        'code' => 1,
                        'msg' => '该商品已全部出库，无法重复操作',
                        'data' => ''
                    ];
                }

                if ($sellGoodsBatchInfo['batch_left_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足',
                        'data' => ''
                    ];
                }

                if ($sellGoodsBatchInfo['rest_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '商品所设置的可出库批次数量不足',
                        'data' => ''
                    ];
                }
            } else {
                //商品批次号信息
                $sellGoodsBatchInfo = StorageBatchModel::select(
                    'a.*',
                    'type_id',
                    'in_storage_num',
                    'b.type_id as materiel_type_id',
                    'd.materiel_name',
                    'd.type_name',
                    'd.materiel_no',
                    'b.storage_id',
                    'c.storage_name',
                    'c.storage_address',
                    'd.materiel_class_id',
                    'e.class_name',
                    'e.class_no',
                    'materiel_mean_cost',
                    'alert_num',
                    'b.virtual_storage_num'
                )
                    ->from('storage_batch as a')
                    ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                    ->leftJoin('storage as c', 'c.id', '=', 'b.storage_id')
                    ->leftJoin('materiel_type as d', 'd.id', '=', 'b.type_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.materiel_class_id')
                    ->where('batch_no', $data['batch_no'])
                    ->first();

                $sellGoodsBatchInfo['price'] = $sellGoodsBatchInfo['materiel_mean_cost'];

                if (empty($sellGoodsBatchInfo)) {
                    return ['code' => 1, 'msg' => '无此批次信息', 'data' => ''];
                }

                //销售单内商品信息
                $sellGoodsInfo = SellGoodsDetail::where([
                    'sell_id' => $data['sell_id'],
                    'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id']
                ])->first();

                if (empty($sellGoodsInfo)) {
                    return ['code' => 1, 'msg' => '当前批次号不属于该商品', 'data' => ''];
                }
//
                if ($sellGoodsInfo['num'] == $sellGoodsInfo['out_num']) {
                    return [
                        'code' => 1,
                        'msg' => '该商品已全部出库，无法重复操作',
                        'data' => ''
                    ];
                }

                if ($sellGoodsBatchInfo['batch_left_num'] < 1) {
                    return [
                        'code' => 1,
                        'msg' => '批次库存数量不足',
                        'data' => ''
                    ];
                }

                $sellGoodsBatchInfo['storage_batch_id'] = $sellGoodsBatchInfo['id'];
                $sellGoodsBatchInfo['batch_id'] = $sellGoodsBatchInfo['id'];
                $sellGoodsBatchInfo['id'] = $sellGoodsInfo['id'];
                $sellGoodsBatchInfo['sell_goods_id'] = 0;
            }
        } else {
            $sellGoodsBatchInfo = SellGoodsDetailModel::select(
                'a.id',
                'a.materiel_type_id',
                'e.materiel_name',
                'e.type_name',
                'e.materiel_no',
                'c.id as storage_batch_id',
                'batch_left_num',
                'in_storage_num',
                'storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.id as storage_manage_id',
                'e.materiel_class_id',
                'f.class_name',
                'f.class_no',
                'materiel_mean_cost',
                'alert_num',
                'c.id as batch_id',
                'a.num',
                'a.out_num',
                'a.price',
                'b.virtual_storage_num'
            )
                ->from('sell_goods_detail as a')
                ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
                ->leftJoin('storage_batch as c', 'c.storage_manage_id', '=', 'b.id')
                ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
                ->where('batch_no', $data['batch_no'])
                ->where('a.sell_id', $data['sell_id'])
                ->orderBy('batch_left_num', 'desc')
                ->first();

            if (empty($sellGoodsBatchInfo)) {
                return [
                    'code' => 1,
                    'msg' => '销售单内无此批次信息',
                    'data' => ''
                ];
            }
        }

        if ($sellGoodsBatchInfo['in_storage_num'] <= 0) {
            return [
                'code' => 1,
                'msg' => '商品库存数量不足',
                'data' => ''
            ];
        }
        if ($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
            return ['code' => 1, 'msg' => '商品虚拟库存数量不足', 'data' => ''];
        }
        $logOutInfo = [
            'type' => 4,
            'storage_batch_id' => $sellGoodsBatchInfo['storage_batch_id'],
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'out_storage_time' => time(),
            'fact_out_time' => time(),
            'created_at' => time()
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
        );

        MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name']
        );

        MessageService::sendOutSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['storage_name'],
            1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['alert_num']
        );

        DB::beginTransaction();

        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);

            SellGoodsDetailBatchModel::where('id', $sellGoodsBatchInfo['sell_goods_id'])
                ->decrement('rest_num', 1);

            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - 1")
                ]);

            StorageBatchModel::where('id', $sellGoodsBatchInfo['batch_id'])
                ->decrement('batch_left_num', 1);

            LogOutStorageModel::insert($logOutInfo);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('快速出库异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '快速出库异常', 'data' => ''];
        }
    }

    //商品ID识别-销售单快速出库
    static private function goodsSellFastOut($data)
    {
        $sellGoodsBatchInfo = SellGoodsDetailModel::select(
            'a.id',
            'a.materiel_type_id',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'in_storage_num',
            'storage_id',
            'd.storage_name',
            'd.storage_address',
            'b.id as storage_manage_id',
            'e.materiel_class_id',
            'f.class_name',
            'f.class_no',
            'materiel_mean_cost',
            'alert_num',
            'a.num',
            'a.out_num',
            'a.price',
            'b.virtual_storage_num',
            'a.price'
        )
            ->from('sell_goods_detail as a')
            ->leftJoin('sell as c', 'c.id', '=', 'a.sell_id')
            ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
            ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
            ->where('e.id', $data['batch_no'])
            ->where('a.sell_id', $data['sell_id'])
            ->where('a.warehouse_id', $data['storage_id'])
            /*  ->where('a.shelf_id',$data['shelf_id'])
                ->where('a.location_id',$data['location_id'])*/
            ->where('e.delete_flag', 0)
            ->where('b.delete_flag', 0)
            ->where('c.delete_flag', 0)
            ->where('c.out_status', '!=', 2)
            ->first();

        if (empty($sellGoodsBatchInfo)) {
            return ['code' => 1, 'msg' => '销售单内无此批次信息', 'data' => ''];
        }
        if ($sellGoodsBatchInfo['is_use_serial'] == 1) {

            return ['code' => 1, 'msg' => '您开启了序列号，请选择序列号出库！', 'data' => ''];
        }
        if (!OperMainAccountModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->exists()) {
            if ($sellGoodsBatchInfo['in_storage_num'] <= 0) {
                return ['code' => 1, 'msg' => '商品库存数量不足', 'data' => ''];
            }
        }

//        if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
//            return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
//        }
        if ($sellGoodsBatchInfo['num'] - $sellGoodsBatchInfo['out_num'] <= 0) {
            return ['code' => 1, 'msg' => '销售单，商品已出库', 'data' => ''];
        }
        //库存数达到预警
//        $sortFlag = 0;
//        if($sellGoodsBatchInfo['in_storage_num']-1 <= $sellGoodsBatchInfo['alert_num']) {
//            $sortFlag = 1;
//        }
        $logOutInfo = [
            'type' => 4,
            'storage_batch_id' => "",
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            /*  'shelf_id' => $data['shelf_id'],
            'location_id' => $data['location_id'],*/
            'out_storage_time' => $data['time'],
            'fact_out_time' => $data['time'],
            'created_at' => $data['time']
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
        );

        MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
            $sellGoodsBatchInfo['storage_name'],
            $sellGoodsBatchInfo['storage_id'],

        );

        MessageService::sendOutSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['storage_name'],
            1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['alert_num']
        );

        $list = SellGoodsDetail::select('num', 'out_num')
            ->where(['sell_id' => $data['sell_id']])->get()->toArray();
        $num = 0;
        foreach ($list as $k => $v) {
            $num += $v['num'] - $v['out_num'];
        }
        DB::beginTransaction();

        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);
            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    //'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
//                    'sort_flag'=>$sortFlag
                ]);
            if ($num == 1) {
                SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                    ->update(['out_status' => 1]);
                sellModel::where(['id' => $data['sell_id']])->update(['out_status' => 2]);
            } else {
                sellModel::where(['id' => $data['sell_id']])->update(['out_status' => 1]);
            }
            LogOutStorageModel::insert($logOutInfo);
            MaterielTypeModel::where(['id' => $sellGoodsBatchInfo['materiel_type_id']])->update(['price_last' => $sellGoodsBatchInfo['price']]);

            CommonService::setAlertFlag($data['main_id']);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('商品ID扫码，出库失败' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '商品ID扫码，出库失败!', 'data' => ''];
        }
    }

    //商品ID识别-销售单快速出库
    public static function sellGoodsBarCodeFastOut($data)
    {
        $sellGoodsBatchInfo = SellGoodsDetailModel::select(
            'a.id',
            'a.materiel_type_id',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'in_storage_num',
            'storage_id',
            'd.storage_name',
            'd.storage_address',
            'b.id as storage_manage_id',
            'e.materiel_class_id',
            'f.class_name',
            'f.class_no',
            'materiel_mean_cost',
            'b.alert_num',
            'a.num',
            'a.out_num',
            'a.price',
            'b.virtual_storage_num',
            'e.is_use_serial'
        )
            ->from('sell_goods_detail as a')
            ->leftJoin('sell as c', 'c.id', '=', 'a.sell_id')
            ->leftJoin('storage_manage as b', 'a.materiel_type_id', '=', 'b.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'b.storage_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
            ->leftJoin('materiel_class as f', 'f.id', '=', 'e.materiel_class_id')
            ->where(function ($query) use ($data) {
                if (strpos($data['batch_no'], 'SMYCYJ') != false) {
                    $code = explode('SMYCYJ', $data['batch_no'])[0];
                    $query->where('e.inventory_code', $code);
                } else {
                    $query->where('e.bar_code', $data['batch_no']);
                }
            })
            ->where('a.sell_id', $data['sell_id'])
            ->where('a.warehouse_id', $data['storage_id'])
            /* ->where('a.shelf_id',$data['shelf_id'])
            ->where('a.location_id',$data['location_id'])*/
            ->where('e.delete_flag', 0)
            ->where('b.delete_flag', 0)
            ->where('c.delete_flag', 0)
            ->where('c.out_status', '!=', 2)
            ->first();

        if (empty($sellGoodsBatchInfo)) {
            return ['code' => 1, 'msg' => '销售单内无此批次信息', 'data' => ''];
        }
        if ($sellGoodsBatchInfo['is_use_serial'] == 1) {

            return ['code' => 1, 'msg' => '您开启了序列号，请选择序列号出库！', 'data' => ''];
        }
        if (!OperMainAccountModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->exists()) {
            if ($sellGoodsBatchInfo['in_storage_num'] <= 0) {
                return ['code' => 1, 'msg' => '商品库存数量不足', 'data' => ''];
            }
        }

//            if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
//                return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
//            }
        if ($sellGoodsBatchInfo['num'] - $sellGoodsBatchInfo['out_num'] <= 0) {
            return ['code' => 1, 'msg' => '销售单，商品已出库', 'data' => ''];
        }
        //库存数达到预警
//            $sortFlag = 0;
//            if($sellGoodsBatchInfo['in_storage_num']-1 <= $sellGoodsBatchInfo['alert_num']) {
//                $sortFlag = 1;
//            }
        $logOutInfo = [
            'type' => 4,
            'storage_batch_id' => "",
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            /*'shelf_id' => $data['shelf_id'],
                'location_id' => $data['location_id'],*/
            'out_storage_time' => $data['time'],
            'fact_out_time' => $data['time'],
            'created_at' => $data['time']
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
        );

        MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
            $sellGoodsBatchInfo['storage_name'],
            $sellGoodsBatchInfo['storage_id'],
        );

        MessageService::sendOutSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['storage_name'],
            1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['alert_num']
        );

        $list = SellGoodsDetail::select('num', 'out_num')
            ->where(['sell_id' => $data['sell_id']])->get()->toArray();
        $num = 0;
        foreach ($list as $k => $v) {
            $num += $v['num'] - $v['out_num'];
        }
        DB::beginTransaction();
        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);
            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    //'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
//                    'sort_flag'=>$sortFlag
                ]);
            if ($num == 1) {
                SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                    ->update(['out_status' => 1]);
                sellModel::where(['id' => $data['sell_id']])->update(['out_status' => 2]);
            } else {
                sellModel::where(['id' => $data['sell_id']])->update(['out_status' => 1]);
            }
            LogOutStorageModel::insert($logOutInfo);
            MaterielTypeModel::where(['id' => $sellGoodsBatchInfo['materiel_type_id']])->update(['price_last' => $sellGoodsBatchInfo['price']]);
            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('条形码扫码出库失败' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //销售单快速出库(序列号)
    static private function serialMaterielSellFastOut($data)
    {
        $sInfo = SerialNumberModel::where([
            'serial_no' => $data['batch_no'],
            'goods_id' => $data['goods_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0
        ])->first();
        if (!empty($sInfo)) {
            if ($sInfo['status'] == 0) {
                return ['code' => 1, 'msg' => '序列号已使用,无法出库', 'data' => ''];
            }
            if (!empty($sInfo['parent_id'])) {
                return ['code' => 1, 'msg' => '该商品作为套餐中的套件使用,请整件出库', 'data' => ''];
            }
        } else {
            return ['code' => 1, 'msg' => '序列号商品不存在，无法出库', 'data' => ''];
        }
        $sellGoodsBatchInfo = SellGoodsDetailModel::select(
            'a.id',
            'a.materiel_type_id',
            'f.materiel_name',
            'f.type_name',
            'f.materiel_no',
            'a.num',
            'a.out_num',
            'in_storage_num',
            'storage_id',
            'e.storage_name',
            'e.storage_address',
            'd.id as storage_manage_id',
            'f.materiel_class_id',
            'g.class_name',
            'g.class_no',
            'materiel_mean_cost',
            'alert_num',
            'c.id as serial_id',
            'a.price',
            'c.status as serial_status',
            'd.virtual_storage_num',
            'f.is_product_materiel',
            'c.parent_id',
            'c.id as serial_id',
            'c.serial_no'
        )
            ->from('sell_goods_detail as a')
            ->leftJoin('serial_number as c', 'c.goods_id', '=', 'a.materiel_type_id')
            ->leftJoin('storage_manage as d', 'd.id', '=', 'c.storage_manage_id')
            ->leftJoin('storage as e', 'e.id', '=', 'd.storage_id')
            ->leftJoin('materiel_type as f', 'f.id', '=', 'd.type_id')
            ->leftJoin('materiel_class as g', 'g.id', '=', 'f.materiel_class_id')
            ->where('c.id', $data['goods_id'])
            ->where('serial_no', $data['batch_no'])
            ->where('a.warehouse_id', $data['storage_id'])
            /* ->where('a.shelf_id',$data['shelf_id'])
            ->where('a.location_id',$data['location_id'])*/
            ->where('a.sell_id', $data['sell_id'])
            ->first();

        //商品已设置批次号
        if (!empty($sellGoodsBatchInfo)) {
            if ($sellGoodsBatchInfo['num'] == $sellGoodsBatchInfo['out_num']) {
                return ['code' => 1, 'msg' => '该商品已全部出库，无法重复操作', 'data' => ''];
            }

            if ($sellGoodsBatchInfo['serial_status'] == 0) {
                return ['code' => 1, 'msg' => '该商品序列号，已使用', 'data' => ''];
            }
        } else {
            return ['code' => 1, 'msg' => '没有找到对应的商品，非常抱歉！', 'data' => ''];
        }
        if (!OperMainAccountModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->exists()) {
            if ($sellGoodsBatchInfo['in_storage_num'] <= 0) {
                return ['code' => 1, 'msg' => '商品库存数量不足', 'data' => ''];
            }
        }
//            if($sellGoodsBatchInfo['virtual_storage_num'] <= 0) {
//                return ['code' => 1,'msg' => '商品虚拟库存数量不足','data' => ''];
//            }
        //库存数达到预警
//        $sortFlag = 0;
//        if($sellGoodsBatchInfo['in_storage_num']-1 <= $sellGoodsBatchInfo['alert_num']) {
//            $sortFlag = 1;
//        }
        $logOutInfo = [
            'type' => 4,
            'storage_id' => $sellGoodsBatchInfo['storage_id'],
            'storage_name' => $sellGoodsBatchInfo['storage_name'],
            'storage_address' => $sellGoodsBatchInfo['storage_address'],
            'curr_storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id'],
            'materiel_class_id' => $sellGoodsBatchInfo['materiel_class_id'],
            'materiel_class_name' => $sellGoodsBatchInfo['class_name'],
            'materiel_class_no' => $sellGoodsBatchInfo['class_no'],
            'materiel_type_id' => $sellGoodsBatchInfo['materiel_type_id'],
            'materiel_name' => $sellGoodsBatchInfo['materiel_name'],
            'type_name' => $sellGoodsBatchInfo['type_name'],
            'materiel_no' => $sellGoodsBatchInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $sellGoodsBatchInfo['in_storage_num'],
            'next_storage_num' => $sellGoodsBatchInfo['in_storage_num'] - 1,
            'sell_price' => $sellGoodsBatchInfo['price'],
            'materiel_mean_cost' => $sellGoodsBatchInfo['materiel_mean_cost'],
            'all_id_type' => 2,
            'all_id' => $data['sell_id'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            /*'shelf_id' => $data['shelf_id'],
                'location_id' => $data['location_id'],*/
            'out_storage_time' => $data['time'],
            'fact_out_time' => $data['time'],
            'created_at' => $data['time'],
            'serial_number' => $data['batch_no']
        ];

        MessageService::sendAlertSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['alert_num'],
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['storage_name'],
            1
        );

        MessageService::sendShortSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $data,
            $sellGoodsBatchInfo['storage_name'],
            $sellGoodsBatchInfo['storage_id'],
        );

        MessageService::sendOutSms(
            $sellGoodsBatchInfo['materiel_name'],
            $sellGoodsBatchInfo['type_name'],
            $sellGoodsBatchInfo['in_storage_num'] - 1,
            $sellGoodsBatchInfo['storage_name'],
            1,
            $data,
            $sellGoodsBatchInfo['storage_id'],
            $sellGoodsBatchInfo['alert_num']
        );

        DB::beginTransaction();
        try {
            SellGoodsDetailModel::where('id', $sellGoodsBatchInfo['id'])
                ->increment('out_num', 1);
            StorageManageModel::where('id', $sellGoodsBatchInfo['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw("in_storage_num - 1"),
                    //'virtual_storage_num' => DB::raw("virtual_storage_num - 1"),
//                'sort_flag'=>$sortFlag
                ]);
            LogOutStorageModel::insert($logOutInfo);
            $arr = [
                'status' => 1,
                'main_id' => $data['main_id'],
                'sell_id' => $data['sell_id'],
                'serial_number' => $data['batch_no'],
                'type_id' => $sellGoodsBatchInfo['materiel_type_id']
            ];
            SellOutSerialNumbersModel::insert($arr);
            SerialNumberModel::where([
                'delete_flag' => 0,
                'serial_no' => $sellGoodsBatchInfo['serial_no'],
                'goods_id' => $sellGoodsBatchInfo['materiel_type_id'],
                'storage_manage_id' => $sellGoodsBatchInfo['storage_manage_id']
            ])->update(['status' => 0]);
            if ($sellGoodsBatchInfo['is_product_materiel'] == 1 && empty($sellGoodsBatchInfo['parent_id'])) {
                if (!empty($sellGoodsBatchInfo['serial_id'])) {
                    SerialNumberModel::where([
                        'detele_flag' => 0,
                        'parent_id' => $sellGoodsBatchInfo['serial_id'],
                    ])->update(['status' => 0]);
                }
            }
            MaterielTypeModel::where(['id' => $sellGoodsBatchInfo['materiel_type_id']])->update(['price_last' => $sellGoodsBatchInfo['price']]);
            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('序列号扫码，出库失败' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '序列号扫码，出库失败！', 'data' => ''];
        }
    }

    /**
     * 清除库存信息
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/13 16:50
     * @return array
     */
    static public function clear($data)
    {
        DB::beginTransaction();

        $storageManageInfo = StorageManageModel::where([
            'storage_id' => $data['id'],
            'delete_flag' => 0
        ])->get()->toArray();

        if (empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '要清除的目标库存信息不存在！', 'data' => ''];
        }

        try {
            //获取库存id
            $storageManageId = [];
            $logData = '';
            foreach ($storageManageInfo as $value) {
                $storageManageId[] = $value['id'];
                $logData .= '商品名称：' . $value['materiel_name'] . '-仓库：' . $value['storage_name'] . ' 库存信息已清除，';
            }
            CommonService::log('清除库存', $data, $logData);
            //清除库存信息
            StorageManageModel::whereIn('id', $storageManageId)
                ->update([
                    'in_storage_num' => 0,
                    'virtual_storage_num' => 0,
                    'delete_flag' => 0
                ]);

            //清除库存批次信息
            StorageBatchModel::whereIn('storage_manage_id', $storageManageId)
                ->update([
                    'batch_left_num' => 0
                ]);
            SerialNumberModel::whereIn('storage_manage_id', $storageManageId)->update(['delete_flag' => 1]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('清除批次信息' . var_export($e->getMessage()));
            return ['code' => 1, 'msg' => '清除失败', 'data' => ''];
        }
    }

    public static function directOutStorageSeveral($data, $time)
    {
        if (empty($data['goods_info'])) {
            return ['code' => 1, 'msg' => '出库商品信息不能为空', 'data' => ''];
        }
        $goodsInfo = json_decode($data['goods_info'], true);
        $logRes = "";
        $serialData = [];
        $logData = [];
        $outStorageData = [];
        $sonSerialData = [];
        DB::beginTransaction();
        try {
            foreach ($goodsInfo as $value) {
                if (!empty($value['storage_id'])
                    && !empty($value['shelf_id'])
                    && !empty($value['location_id'])
                    && empty($value['storageManageId'])
                ) {
                    $value['storageManageId'] = StorageManageModel::query()
                        ->where([
                            'main_id' => $data['main_id'],
                            'storage_id' => $value['storage_id'],
                            'shelf_id' => $value['shelf_id'],
                            'location_id' => $value['location_id'],
                            'type_id' => $value['type_id'],
                            'delete_flag' => 0
                        ])->value('id');
                }
                $storageManageInfo = StorageManageModel::select(
                    'a.id',
                    'a.storage_id',
                    'a.materiel_class_id',
                    'a.type_id',
                    'a.in_storage_num',
                    'a.materiel_mean_cost',
                    'b.class_name as materiel_class_name',
                    'b.class_no as materiel_class_no',
                    'c.is_use_serial',
                    'c.is_product_materiel',
                    'c.materiel_name',
                    'c.type_name',
                    'c.materiel_no',
                    'd.storage_name',
                    'd.storage_address',
                    'a.alert_num',
                    'a.virtual_storage_num',
                    'a.shelf_id',
                    'a.location_id',
                    'c.is_use_serial',
                    'c.cost',
                    'a.delete_flag'
                )
                    ->from('storage_manage as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
                    ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
                    ->where([
                        'a.id' => $value['storageManageId'],
                        'a.main_id' => $data['main_id'],
                    ])->first();

                if (empty($storageManageInfo['id'])) {
                    $goodsName = MaterielTypeModel::query()->where([
                        'id' => $value['type_id']
                    ])->value('materiel_name');
                    throw new \RuntimeException('商品名称:' . $goodsName . '，无库存信息!');
                }
                if (!empty($data['out_type'])) {
                    if ($data['out_type'] == 2 && !empty($value['application_goods_id'])) {
                        $info = ApplicationGoodsModel::query()
                            ->where([
                                'delete_flag' => 0,
                                'id' => $value['application_goods_id']
                            ])->first();
                        if (!empty($info)) {
                            if ($value['num'] > $info['surplus_num']) {
                                throw new \Exception('申请单商品:' . $storageManageInfo['materiel_name'] . '可操作的数量不足，可操作数量为：' . $info['surplus_num']);
                            }
                            $info['surplus_num'] -= $value['num'];
                            $info->save();
                        } else {
                            throw new \Exception('申请单商品:' . $storageManageInfo['materiel_name'] . '，无信息！');
                        }
                    }
                }
                $logRes .= '商品名称：' . $storageManageInfo['materiel_name'] .
                    '出库数量：' . $value['num'] . '仓库名：' . $storageManageInfo['storage_name'] . '、';
                if ($storageManageInfo['is_product_materiel'] && $data['is_use_packages_components']) {
                    //是否套餐当组件使用
                    $requestPackageInfo = [];
                    $requestPackageInfo ['id'] = $storageManageInfo['type_id'];
                    $requestPackageInfo ['materiel_name'] = $storageManageInfo['materiel_name'];
                    $requestPackageInfo ['shelf_id'] = $storageManageInfo['shelf_id'];
                    $requestPackageInfo ['location_id'] = $storageManageInfo['location_id'];
                    $requestPackageInfo ['storage_id'] = $storageManageInfo['storage_id'];
                    $requestPackageInfo ['is_use_serial'] = $storageManageInfo['is_use_serial'];
                    $requestPackageInfo ['num'] = $value['num'];
                    $requestPackageInfo ['client_id'] = $value['client_id'] ?? 0;
                    $data['operation_type'] = 2;
                    $data['all_id_type'] = 0;
                    $requestPackageInfo ['sell_price'] = $value['price'];
                    StorageManageService::packageComponentHandle($requestPackageInfo, $data, 'out');
                } else {
                    if ($storageManageInfo['delete_flag']) {
                        throw new \Exception('商品:' . $storageManageInfo['materiel_name'] . '库存已删除！');
                    }

                    /* if($value['num'] > $storageManageInfo['virtual_storage_num']) {
                        return ['code' => 1, 'msg' => '商品:'.$storageManageInfo['materiel_name'].'可用库存数不足，请重试', 'data' => ''];
                    }*/
                    if (!OperMainAccountModel::query()
                        ->where([
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0
                        ])->exists()) {
                        if ($value['num'] > $storageManageInfo['in_storage_num']) {
                            return ['code' => 1, 'msg' => '商品:' . $storageManageInfo['materiel_name'] . '库存数不足，请重试', 'data' => ''];
                        }
                    }
                    $serialNumberStr = '';
                    if ($storageManageInfo['is_use_serial']) {
                        if (empty($value['serial_no'])) {
                            throw new \Exception('商品:' . $storageManageInfo['materiel_name'] . '已开启序列号，请选择序列号后重试');
                        }
                        $serialIdData = array_filter(explode(',', $value['serial_no']), function ($v) {
                            return $v !== '';
                        });
                        if ($value['num'] > count($serialIdData)) {
                            $shortNum = $value['num'] - count($serialIdData);
                            throw new \Exception('商品:' . $storageManageInfo['materiel_name'] . '出库数量X' . $value['num'] . ',序列号仍缺失X' . $shortNum);
                        }
                        if ($value['num'] < count($serialIdData)) {
                            $shortNum = count($serialIdData) - $value['num'];
                            throw new \Exception('商品:' . $storageManageInfo['materiel_name'] . '出库数量X' . $value['num'] . ',超出序列号所需数量' . $shortNum);
                        }
                        $serialInfo = SerialNumberModel::query()->where([
                            'delete_flag' => 0
                        ])->whereIn('id', $serialIdData)->get()->toArray();

                        foreach ($serialInfo as $serialIdValue) {
                            if ($serialIdValue['delete_flag'] == 1) {
                                throw new \Exception('商品:' . $storageManageInfo['materiel_name'] . '序列号:' . $serialIdValue['serial_no'] . '已被删除');
                            }
                            if ($serialIdValue['status'] == 0) {
                                throw new \Exception('商品:' . $storageManageInfo['materiel_name'] . '序列号:' . $serialIdValue['serial_no'] . '已被使用');
                            }

                            $serialData[] = [
                                'id' => $serialIdValue['id'],
                                'status' => 0
                            ];
                            //检查是否有下一级序列号
                            $hasSonSerialInfo = SerialNumberModel::where([
                                'parent_id' => $serialIdValue,
                                'delete_flag' => 0
                            ])->first();

                            if (!empty($hasSonSerialInfo)) {
                                $sonSerialData[] = $serialIdValue;
                            }
                            $serialNumberStr .= $serialIdValue['serial_no'] . ',';
                        }
                    }
                    $leftStorageNum = $storageManageInfo['in_storage_num'] - $value['num'];
                    $profitOrLossRatio = 0;
                    if ($storageManageInfo['cost'] != 0) {
                        if (empty($data['out_type'])) {
                            if ($value['price'] >= $storageManageInfo['cost']) {//盈
                                $profitOrLossRatio = sprintf('%.6f', (($value['price'] - $storageManageInfo['cost']) / $storageManageInfo['cost']));
                            } else {//亏
                                $profitOrLossRatio = sprintf('%.6f', (($storageManageInfo['cost'] - $value['price']) / $storageManageInfo['cost']));
                            }
                        }
                    }

                    if (empty($value['location_id']) || empty($value['shelf_id'])) {
                        /* if (!empty($data['is_share_shelf_location'])) {
                             throw new \Exception('您开启强制选择货架及库位，请选择！');
                         }*/
                        $shelfInfo = StorageShelfModel::where([
                            'storage_id' => $storageManageInfo['storage_id'],
                            'shelf_type' => 1
                        ])->first();
                        $value['shelf_id'] = $shelfInfo['id'];
                        //获取库位
                        $locationInfo = StorageShelfLocationModel::where([
                            'shelf_id' => $shelfInfo['id'],
                            'location_type' => 1
                        ])->first();
                        $value['location_id'] = $locationInfo['id'];
                    }
                    $logData = [
                        'type' => 2,//type;0:出库;1:调出;2:直接出库;
                        'storage_id' => $storageManageInfo['storage_id'],
                        'storage_name' => $storageManageInfo['storage_name'],
                        'storage_address' => $storageManageInfo['storage_address'],
                        'next_storage_id' => 0,
                        'next_storage_name' => '',
                        'next_storage_address' => '',
                        'curr_storage_manage_id' => $storageManageInfo['id'],
                        'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                        'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                        'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                        'materiel_type_id' => $storageManageInfo['type_id'],
                        'materiel_name' => $storageManageInfo['materiel_name'],
                        'type_name' => $storageManageInfo['type_name'],
                        'materiel_no' => $storageManageInfo['materiel_no'],
                        'operate_num' => $value['num'],
                        'last_storage_num' => $storageManageInfo['in_storage_num'],
                        'next_storage_num' => $storageManageInfo['in_storage_num'] - $value['num'],
                        'sell_price' => $value['price'] ?? 0,
                        'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                        'remark' => empty($value['remark']) ? '' : $value['remark'],
                        'main_id' => $data['main_id'],
                        'user_id' => $data['user_id'],
                        'out_storage_time' => $data['out_storage_time'],
                        'created_at' => $time,
                        'profit_or_loss_ratio' => $profitOrLossRatio,
                        'serial_number' => empty($serialNumberStr) ? '' : substr($serialNumberStr, 0, -1),
                        'location_id' => $value['location_id'],
                        'shelf_id' => $value['shelf_id'],
                        'label_id' => $data['label_id'],
                        'label_name' => $data['label_name'],
                        'general_remarks' => $data['general_remarks'],
                        'client_id' => empty($value['client_id']) ? 0 : $value['client_id'],
                    ];
                    $outStorageData[] = [
                        'id' => $storageManageInfo['id'],
                        'in_storage_num' => $leftStorageNum,
                        // 'virtual_storage_num' => $storageManageInfo['virtual_storage_num'] - $value['num'],
                        //                'sort_flag' => $sortFlag,
                        'operate_num' => $value['num'],
                        'materiel_name' => $storageManageInfo['materiel_name'],
                        'type_name' => $storageManageInfo['type_name'],
                        'alert_num' => $storageManageInfo['alert_num'],
                        'storage_id' => $storageManageInfo['storage_id'],
                        'storage_name' => $storageManageInfo['storage_name'],
                        'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                        'batch_list' => $value['batch_list'] ?? 0,
                        'log_id' => LogOutStorageModel::query()->insertGetId($logData),
                        'shelf_name' => StorageShelfModel::query()
                                ->where('id', $value['shelf_id'])
                                ->value('shelf_name') ?? '',
                        'location_name' => StorageShelfLocationModel::query()
                                ->where('id', $value['location_id'])
                                ->value('location_name') ?? '',
                    ];
                }
            }
            if (!empty($serialData)) {
                batch()->update(new SerialNumberModel, $serialData, 'id');
            }
            //更新已出库序列号含有下一级序列号的状态
            if (!empty($sonSerialData)) {
                SerialNumberModel::whereIn('parent_id', $sonSerialData)->update(['status' => 0]);
            }
            if (!empty($outStorageData)) {
                $outStorageContent = [];
                $batchArr = [];
                foreach ($outStorageData as $key => $val) {
                    //扣除批次号
                    $batchArr = self::batchNoHandle($val, $val['batch_list'], $val['operate_num'], $data);
                    $logData[$key]['batch_no'] = $batchArr;
                    MessageService::sendAlertSms(
                        $val['materiel_name'],
                        $val['type_name'],
                        $val['in_storage_num'],
                        $val['alert_num'],
                        $data,
                        $val['storage_id'],
                        $val['storage_name'],
                        $val['operate_num']
                    );

                    MessageService::sendShortSms(
                        $val['materiel_name'],
                        $val['type_name'],
                        $val['in_storage_num'],
                        $data,
                        $val['storage_name'],
                        $val['storage_id']
                    );

                    MessageService::sendOutSms(
                        $val['materiel_name'],
                        $val['type_name'],
                        0,
                        $val['storage_name'],
                        $val['operate_num'],
                        $data,
                        $val['storage_id'],
                        $val['alert_num'],
                        $val['log_id']
                    );
                    $outStorageContent[] = [
                        'id' => $val['id'],
                        'in_storage_num' => $val['in_storage_num'],
                        //'virtual_storage_num' => $val['virtual_storage_num'],
//                        'sort_flag' => $val['sort_flag'],
                    ];
                }
                batch()->update(new StorageManageModel, $outStorageContent, 'id');
                foreach ($outStorageData as $oVal) {
                    $outInfo = LogOutStorageModel::query()->where('id', $oVal['log_id'])->first();
                    $manaInfo = StorageManageModel::query()->where([
                        'delete_flag' => 0,
                        ['in_storage_num', '>', 0],
                        'main_id' => $outInfo['main_id'],
                        'shelf_id' => $outInfo['shelf_id'],
                        'storage_id' => $outInfo['storage_id'],
                        'location_id' => $outInfo['location_id']
                    ])->first();
                    /*if ($manaInfo === null) {
                        $logInfo = StorageShelfLocationModel::query()
                            ->where([
                                'id' => $outInfo['location_id'],
                                'main_id' => $outInfo['main_id'],
                            ])->first();
                        if (!empty($logInfo)) {
                            $outInfo->general_remarks .= '日志编号：' . $logInfo['log_no'];
                            $outInfo->save();
                            $locaLogData = [
                                'conent1' => date('Y.m.d', time()),
                                'conent2' => $oVal['shelf_name'] . '-' . $oVal['location_name'] . '-' . $oVal['materiel_name'],
                                'conent3' => '已售出',
                                'conent4' => '记录档(' . $logInfo['log_no'] . ')',
                                'type' => 1,
                                'type_time' => date('Y.m.d', time()),
                                'log_no' => $logInfo['log_no'],
                                'main_id' => $outInfo['main_id'],
                                'user_id' => $outInfo['user_id']
                            ];
                            LocationLogModel::query()->where([
                                'type' => 0,
                                'log_no' => $logInfo['log_no'],
                                'id' => $outInfo['location_id'],
                                'main_id' => $outInfo['main_id'],
                            ])->update([
                                'type' => 1,
                                'type_time' => date('Y.m.d', time())
                            ]);
                            LocationLogModel::query()->insertGetId($locaLogData);
                        }
                    }*/
                }
            }
            /* if (!empty($logData)) {
                 LogOutStorageModel::insert($logData);
             }*/
            CommonService::setAlertFlag($data['main_id']);
            CommonService::operateResult($data['user_id'], $time, $data, $logRes);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('批量出库异常' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //获取套餐总成本
    static public function getPackageCost($package_id)
    {
        $data = PackageContentModel::select(
            DB::raw('SUM(num * cost) as total_cost')
        )
            ->from('package_content as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->where('a.package_id', $package_id)
            ->groupBy('package_id')
            ->first();

        return $data['total_cost'];
    }

    public static function storeGoods($data, $time)
    {
        if (!empty($data['goods_info'])) {
            $goods = json_decode($data['goods_info'], true);

            $serialDataArr = [];
            foreach ($goods as $key => $value) {

                //没有传货架库位，使用默认货架库位
                if (empty($data['shelf_id']) || empty($data['location_id'])) {
                    $sfData = ShelfService::get_default($data['storage_id']);

                    if (!empty($sfData)) {
                        $shelf_id = $sfData['id'];
                        $lData = ShelfService::get_default($shelf_id, 2);
                        $location_id = $lData['id'];
                    } else {
                        $shelf_id = 0;
                        $location_id = 0;
                        $data['shelf_id'] = 0;
                        $data['location_id'] = 0;
                    }
                } else {
                    $shelf_id = $data['shelf_id'];
                    $location_id = $data['location_id'];
                }

                $materielTypeInfo = MaterielsTypeModel::select(
                    'a.id',
                    'materiel_name',
                    'type_name',
                    'materiel_no',
                    'b.id as materiel_class_id',
                    'b.class_name',
                    'b.class_no',
                    'c.id as first_class',
                    'cost'
                )
                    ->from('materiel_type as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                    ->where([
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                        'a.main_id' => $data['main_id'],
                        'a.delete_flag' => 0,
                    ])
                    ->first();

                if (empty($materielTypeInfo)) {
                    throw new Exception('物料`' . $value['materiel_name'] . '-' . $value['type_name'] . '`不存在');
                }

                //仓库信息
                $storageInfo = StorageModel::where([
                    'storage_name' => $data['storage_name'],
                    'id' => $data['storage_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0,
                ])->first();

                if (empty($storageInfo)) {
                    throw new Exception('仓库`' . $data['storage_name'] . '`不存在');

                }

                //检查库存信息
                $checkStorageManage = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $data['storage_id'],
                    'main_id' => $data['main_id'],
                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                ])->first();

                $minfo = MaterielsTypeModel::select('is_use_serial')->where('id', $materielTypeInfo['id'])->first();
                $serialData = [];
                if ($minfo['is_use_serial'] == 1) {
                    if (empty($value['serial_no'])) {
                        throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '已开启序列号选项，请填写序列号');
                    }

                    $serialData = array_filter(explode(',', $value['serial_no']), function ($v) {
                        return $v !== '';
                    });

                    if ($value['num'] != count($serialData)) {
                        throw new Exception('序列号个数与入库数量不符');
                    }

                    $checkSerialInfo = SerialNumberModel::where([
                        'goods_id' => $materielTypeInfo['id'],
                        'delete_flag' => 0
                    ])->whereIn('serial_no', $serialData)
                        ->first();
                    if (!empty($checkSerialInfo)) {
                        throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '中序列号:' . $checkSerialInfo['serial_no'] . '已存在');
                    }
                }

                $newStorageManageInfo = [];//新物料入库
                $updateInStorageNum = [];//已有物料入库
                if (empty($checkStorageManage)) {
                    $newStorageManageInfo = [
                        'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                        'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                        'materiel_class_no' => empty($materielTypeInfo['class_no']) ? '' : $materielTypeInfo['class_no'],//物料二级分类名称
                        'type_id' => $materielTypeInfo['id'],//物料id
                        'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                        'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                        'materiel_no' => empty($materielTypeInfo['materiel_no']) ? '' : $materielTypeInfo['materiel_no'],//物料编号
                        'materiel_mean_cost' => $materielTypeInfo['cost'] == 0 ? 0 : $materielTypeInfo['cost'],
                        'storage_id' => $storageInfo['id'],//仓库id
                        'storage_name' => $storageInfo['storage_name'],//仓库名
                        'storage_address' => $storageInfo['storage_address'],//仓库地址
                        'in_storage_num' => $value['num'],//采购单内物料商品入库数量
                        'virtual_storage_num' => $value['num'],
                        'main_id' => $data['main_id'],//主账号id
                        'in_storage_time' => $time,//入库时间
                        'alert_num' => $data['alert_num'],
                        'created_at' => $time,

                        'shelf_id' => $shelf_id,
                        'location_id' => $location_id,
                    ];

                    MessageService::sendInSms(
                        '无',
                        $materielTypeInfo['materiel_name'],
                        $materielTypeInfo['type_name'],
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $data,
                        $value['num'],
                        $value['num']
                    );
                } else {
                    $updateInStorageNum = [
                        'id' => $checkStorageManage->id,
                        'in_storage_num' => $value['num'],
                        'alert_num' => $data['alert_num'],
                        'remark' => $data['remark'],
                        'materiel_mean_cost' => $materielTypeInfo['cost'],
                    ];

                    MessageService::sendInSms(
                        '无',
                        $materielTypeInfo['materiel_name'],
                        $materielTypeInfo['type_name'],
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $data,
                        $value['num'],
                        $checkStorageManage['in_storage_num'] + $value['num']
                    );
                }

                $inStorageNum = !empty($checkStorageManage) ? $checkStorageManage['in_storage_num'] : 0;

                //入库操作记录
                $logInStorage = [
                    'type' => 2,//日志类型;0:入库;1:调拨入库;2:直接入库;
                    'storage_id' => $storageInfo['id'],//入库目标仓库id
                    'storage_name' => $storageInfo['storage_name'],//仓库名
                    'storage_address' => $storageInfo['storage_address'],//仓库地址
                    'last_storage_id' => 0,//调拨前所在仓库id
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                    'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                    'materiel_class_no' => empty($materielTypeInfo['class_no']) ? '' : $materielTypeInfo['class_no'],//物料二级分类名称
                    'materiel_type_id' => $materielTypeInfo['id'],//物料id
                    'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                    'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                    'materiel_no' => empty($materielTypeInfo['materiel_no']) ? '' : $materielTypeInfo['materiel_no'],//物料编号
                    'operate_num' => $value['num'],//操作数量
                    'last_storage_num' => $inStorageNum,//操作前库存数
                    'next_storage_num' => $inStorageNum + $value['num'],//操作后库存数
                    'materiel_mean_cost' => 0,//物料均价
                    'in_storage_time' => $time,//入库时间
                    'remark' => $data['remark'],//备注
                    'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
                    'all_id' => 0,//单据id
                    'user_id' => $data['user_id'],//操作人id
                    'main_id' => $data['main_id'],//主账号id
                    'created_at' => $time,
                    'serial_number' => !empty($value['serial_no']) ? $value['serial_no'] : '',
                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                ];

                $meanCost = 0;
                if (!empty($newStorageManageInfo)) {
                    $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                    $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
                }

                if (!empty($updateInStorageNum)) {
                    StorageManageModel::where('id', $updateInStorageNum['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + ' . $value['num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + ' . $value['num']),
                            'alert_num' => $data['alert_num'],
                            'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                            'delete_flag' => 0
                        ]);

                    $meanCost = $updateInStorageNum['materiel_mean_cost'];
                    $newStorageManageId = $updateInStorageNum['id'];
                }

                $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';

                do {
                    $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                } while (!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));

                StorageBatchModel::insert([
                    'batch_no' => $batchNo,
                    'storage_manage_id' => $newStorageManageId,
                    'batch_num' => $value['num'],
                    'batch_left_num' => $value['num'],
                    'batch_cost' => $meanCost,
                    'materiel_id' => 0,
                    'main_id' => $data['main_id'],
                    'created_at' => $time
                ]);

                $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

                LogInstorageModel::insert($logInStorage);

                if (!empty($serialData)) {
                    foreach ($serialData as $serialValue) {
                        $serialDataArr[] = [
                            'serial_no' => $serialValue,
                            'batch_no' => $batchNo,
                            'storage_manage_id' => $newStorageManageId,
                            'goods_id' => $materielTypeInfo['id'],
                            'created_at' => $time,
                            'main_id' => $data['main_id']
                        ];
                    }
                }
            }

            if (!empty($serialDataArr)) {
                SerialNumberModel::insert($serialDataArr);
            }
        }

        return true;
    }

    static public function oneKeyClear($data)
    {
        if ($data['code'] == '888888') {
            Redis::setex($data['mobile'] . '_one_clear', 300, '888888');
        }
        //比对用户输入的code和短信发送的code是否一致
        if (!Redis::exists($data['mobile'] . '_one_clear')) {
            return ['code' => 1, 'msg' => '您输入的验证码无效，请重试', 'data' => ''];
        } else {
            if ($data['code'] == Redis::get($data['mobile'] . '_one_clear')) {//验证码一致
                $checkStorage = StorageManageModel::where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])
                    ->first();

                $checkMateriel = MaterielsTypeModel::where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])
                    ->first();

                $checkClass = MaterielClassModel::where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id']
                ])
                    ->first();
                $reg = '';
                DB::beginTransaction();

                try {
                    if (!empty($data['clear_finance'])) {
                        if ($data['clear_finance'] == 1) {
                            OverflowBreakageModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            SalesReturnModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            SellModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            MaterielModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            ProductOrderModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);

                            TallyModel::where('main_id', $data['main_id'])
                                ->update(['delete_flag' => 1]);
                        }
                        $reg .= '一键清除财务记录、';
                    }

                    //清除库存
                    if ($data['clear_storage']) {
                        self::clearStorage($data);
                        $reg .= '仓库库存、';
                    }

                    if ($data['clear_materiel']) {
                        if (!empty($checkStorage)) {
                            self::clearStorage($data);
                        }
                        if (!empty($checkMateriel)) {
                            self::clearMateriel($data);
                        }
                        $reg .= '商品信息、';
                    }

                    if ($data['clear_class']) {
                        if (!empty($checkStorage)) {
                            self::clearStorage($data);
                        }
                        if (!empty($checkMateriel)) {
                            self::clearMateriel($data);
                        }
                        if (!empty($checkClass)) {
                            self::clearClass($data);
                        }

                        $reg .= '分类信息、';
                    }

                    if (!empty($data['clear_empty_img'])) {
                        $res = self::clearImg($data);
                        if (isset($res['code'])) {
                            if ($res['code'] === 1) {
                                throw new \Exception($res['msg']);
                            }
                        }
                        $reg .= '空余图片信息、';
                    }

                    if (!empty($data['clear_all_img'])) {
                        $res = self::clearImg($data, 2);
                        if (isset($res['code'])) {
                            if ($res['code'] === 1) {
                                throw new \Exception($res['msg']);
                            }
                        }
                        $reg .= '空余图片信息、';
                    }

                    if (isset($data['clear_log'])) {
                        self::clearLog($data);
                        $reg .= '操作记录';
                    }
                    $logData = '清除项：（' . $reg . '）';
                    CommonService::operateResult($data['user_id'], $data['logTime'], $data, $logData);
                    DB::commit();
                    Redis::del($data['mobile'] . '_one_clear');//一键清除后销毁验证码
                    return ['code' => 0, 'msg' => 'success', 'data' => ''];
                } catch (Exception $e) {
                    DB::rollBack();
                    Log::debug('一键清除异常:' . var_export($data, true));
                    return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
                }
            } else {
                return ['code' => 1, 'msg' => '您输入的验证码有误，请重新输入', 'data' => ''];
            }
        }
    }

    private static function clearImg($data, $type = 1)
    {

        return UploadImgService::handleImg($data, $type);
    }

    //一键清除库存
    static private function clearStorage($data)
    {
        $list = StorageManageModel::select('id')
            ->where([
                'delete_flag' => 0,
                'main_id' => $data['main_id']
            ])->get()->toArray();
        if (!empty($list)) {
            foreach ($list as $val) {
                SerialNumberModel::where(['storage_manage_id' => $val['id']])->update(['delete_flag' => 1]);
            }
            StorageManageModel::where([
                'delete_flag' => 0,
                'main_id' => $data['main_id']
            ])->update([
                'delete_flag' => 1
            ]);
        }
        StorageModel::where([
            'delete_flag' => 0,
            'main_id' => $data['main_id']
        ])->update([
            'delete_flag' => 1
        ]);
        return true;
    }

    //一键清除商品信息
    static private function clearMateriel($data)
    {
        MaterielsTypeModel::where([
            'delete_flag' => 0,
            'main_id' => $data['main_id']
        ])
            ->update(['delete_flag' => 1]);

        return true;
    }

    static private function clearClass($data)
    {
        MaterielClassModel::where([
            'delete_flag' => 0,
            'main_id' => $data['main_id']
        ])
            ->update(['delete_flag' => 1]);

        return true;
    }

    static public function storageManageIn($data)
    {
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.type_id',
            'in_storage_num',
            'virtual_storage_num',
            'materiel_mean_cost',
            'b.type_name',
            'b.materiel_name',
            'b.materiel_no',
            'a.materiel_class_id',
            'c.class_name',
            'c.class_no',
            'a.storage_id',
            'd.storage_name',
            'd.storage_address',
            'shelf_id',
            'location_id'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'a.type_id', '=', 'b.id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'a.materiel_class_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->where('a.id', $data['id'])->first();

        DB::beginTransaction();

        if (empty($data['location_id'])) {
            $shelfInfo = StorageShelfModel::where([
                'storage_id' => $storageManageInfo['storage_id'],
                'shelf_type' => 1
            ])->first();

            $data['shelf_id'] = $shelfInfo['id'];

            //获取库位
            $locationInfo = StorageShelfLocationModel::where([
                'shelf_id' => $shelfInfo['id'],
                'location_type' => 1
            ])
                ->first();

            $data['location_id'] = $locationInfo['id'];
        }

        try {
            StorageManageModel::where('id', $data['id'])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num + ' . $data['num']),
                    //'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num'])
                ]);

            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            $checkBatchNo = StorageBatchModel::where('main_id', $data['main_id'])
                ->where('batch_no', $batchNo)->first();

            do {
                $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            } while (!empty($checkBatchNo));

            $batchId = MaterielService::createBatchInfoGetId(
                $batchNo,
                $storageManageInfo['id'],
                $storageManageInfo['materiel_mean_cost'],
                $data['num'],
                0,
                $data['main_id']
            );

            $inLogId = LogInstorageModel::query()->insertGetId([
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_type_id' => $storageManageInfo['type_id'],//物料id
                'batch_id' => $batchId,//物料id
                'materiel_name' => $storageManageInfo['materiel_name'],//物料名称
                'type_name' => $storageManageInfo['type_name'],//物料型号
                'materiel_no' => $storageManageInfo['materiel_no'],//物料编号
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],//物料二级分类主键名称
                'materiel_class_name' => $storageManageInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => $storageManageInfo['class_no'],//物料二级分类编号
                'type' => 2,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                'storage_id' => $storageManageInfo['storage_id'],//仓库主键id
                'storage_name' => $storageManageInfo['storage_name'],//仓库名
                'storage_address' => $storageManageInfo['storage_address'],//仓库地址
                'last_storage_id' => 0,//调拨前所在仓库id
                'operate_num' => $data['num'],//操作数量
                'last_storage_num' => 0,//操作前库存数
                'materiel_mean_cost' => empty($storageManageInfo) ? 0 : $storageManageInfo['materiel_mean_cost'],//物料均价
                'next_storage_num' => $storageManageInfo['in_storage_num'] + $data['num'],//操作后库存数
                'all_id_type' => 0,//单据类型;0:无;1:报溢;2:退货;3:采购;
                'in_storage_time' => time(),//入库时间
                'shelf_id' => $data['shelf_id'],
                'location_id' => $data['location_id'],
                'all_id' => 0,//单据id
                'user_id' => $data['user_id'],//操作人用户id
                'main_id' => $data['main_id'],//主账号id
                'remark' => empty($data['remark']) ? '' : $data['remark'],
                'label_id' => $data['label_id'],
                'label_name' => !empty($data['label_name']) ? $data['label_name'] : "",
                'created_at' => $data['time'],
            ]);

            MessageService::sendInSms(
                time(),
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data,
                $data['num'],
                $storageManageInfo['in_storage_num'] + $data['num'],
                $inLogId
            );
            $logData = '商品名称：' . $storageManageInfo['materiel_name'] . '（' . $storageManageInfo['materiel_no'] . '）' .
                '入库数量：' . $data['num'] . ' 仓库名：' . $storageManageInfo['storage_name'];
            CommonService::operateResult($data['user_id'], $data['time'], $data, $logData);
            CommonService::cancelAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('库存直接入库异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '直接入库失败！', 'data' => ''];
        }
    }

    //直接入库(新建入库)
    static public function directInStorage($data)
    {
        $data['alert_num'] = $data['status'] == 1 ? $data['alert_num'] : 0;
        $data['remark'] = empty($data['remark']) ? '' : $data['remark'];

        $materielTypeInfo = MaterielTypeModel::select(
            'a.id',
            'materiel_name',
            'type_name',
            'materiel_no',
            'b.id as materiel_class_id',
            'b.class_name',
            'b.class_no',
            'c.id as first_class',
            'cost'
        )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
            ->where([
                'materiel_name' => $data['materiel_name'],
                'type_name' => $data['type_name'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
            ])
            ->first();

        if (empty($materielTypeInfo)) {
            return ['code' => 1, 'msg' => '物料`' . $data['materiel_name'] . '-' . $data['type_name'] . '`不存在', 'data' => ''];
        }

        //仓库信息
        $storageInfo = StorageModel::where([
            'storage_name' => $data['storage_name'],
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();

        if (empty($storageInfo)) {
            return ['code' => 1, 'msg' => '仓库`' . $data['storage_name'] . '`不存在', 'data' => ''];
        }

        //检查库存信息
        $checkStorageManage = StorageManageModel::where([
            'type_id' => $materielTypeInfo['id'],
            'storage_id' => $data['storage_id'],
            'main_id' => $data['main_id'],
        ])->first();

        $newStorageManageInfo = [];//新物料入库
        $updateInStorageNum = [];//已有物料入库
        if (empty($checkStorageManage)) {
            $newStorageManageInfo = [
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($materielTypeInfo['class_no']) ? '' : $materielTypeInfo['class_no'],//物料二级分类名称
                'type_id' => $materielTypeInfo['id'],//物料id
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                'materiel_no' => empty($materielTypeInfo['materiel_no']) ? '' : $materielTypeInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $materielTypeInfo['cost'] == 0 ? 0 : $materielTypeInfo['cost'],
                'storage_id' => $storageInfo['id'],//仓库id
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' => $data['num'],//采购单内物料商品入库数量
                //'virtual_storage_num' => $data['num'],
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => time(),//入库时间
                'alert_num' => $data['alert_num'],
                'created_at' => time(),
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $data['num']
            );
        } else {
            $updateInStorageNum = [
                'id' => $checkStorageManage->id,
                'in_storage_num' => $data['num'],
                'alert_num' => $data['alert_num'],
                'remark' => $data['remark'],
                'materiel_mean_cost' => $materielTypeInfo['cost'],
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $checkStorageManage['in_storage_num'] + $data['num']
            );
        }

        $inStorageNum = !empty($checkStorageManage) ? $checkStorageManage['in_storage_num'] : 0;

        //入库操作记录
        $logInStorage = [
            'type' => 2,//日志类型;0:入库;1:调拨入库;2:直接入库;
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($materielTypeInfo['class_no']) ? '' : $materielTypeInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $materielTypeInfo['id'],//物料id
            'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
            'type_name' => $materielTypeInfo['type_name'],//物料型号名称
            'materiel_no' => empty($materielTypeInfo['materiel_no']) ? '' : $materielTypeInfo['materiel_no'],//物料编号
            'operate_num' => $data['num'],//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + $data['num'],//操作后库存数
            'materiel_mean_cost' => 0,//物料均价
            'in_storage_time' => time(),//入库时间
            'remark' => $data['remark'],//备注
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => time()
        ];

        DB::beginTransaction();

        try {
            $meanCost = 0;
            if (!empty($newStorageManageInfo)) {
                $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
            }

            if (!empty($updateInStorageNum)) {
                StorageManageModel::where('id', $updateInStorageNum['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + ' . $data['num']),
                        //'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num']),
                        'alert_num' => $data['alert_num'],
                        'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                        'delete_flag' => 0
                    ]);

                $meanCost = $updateInStorageNum['materiel_mean_cost'];
                $newStorageManageId = $updateInStorageNum['id'];
            }

            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            $checkBatchInfo = StorageBatchModel::where('batch_no', $batchNo)->first();

            do {
                $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            } while (!empty($checkBatchInfo));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageManageId,
                'batch_num' => $data['num'],
                'batch_left_num' => $data['num'],
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => time()
            ]);

            $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

            LogInstorageModel::insert($logInStorage);

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                1,
                $inStorageNum + 1
            );
            $logData = '商品名称：' . $materielTypeInfo['materiel_name'] . '（' . $materielTypeInfo['materiel_no'] . '）' .
                '入库数量：' . $data['num'] . ' 仓库名：' . $storageInfo['storage_name'];
            CommonService::log('直接入库', $data, $logData);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollback();
            Log::debug('新建入库(直接入库：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => "直接入库失败！", 'data' => ''];
        }
    }

    //扫码入库
    public static function scanCodesInStorage($data)
    {
        $goodsId = "";
        $barCode = "";
        $serialNumber = "";
        $clickflag = 0;
        $remark = "";
        $checkSerialInfo = [];
        switch ($data['code_type']) {
            case 0://物料商品id
                if (strpos($data['batch_no'], 'smycg') !== false) {//物料商品id
                    $data['batch_no'] = substr($data['batch_no'], 5, strlen($data['batch_no']) - 1);
                    $goodsId = $data['batch_no'];
                    $remark = "商品ID";
                }
                break;
            case 1://序列号
                if (!empty($data['goods_id']) && !empty($data['batch_no'])) {
                    $goodsId = $data['goods_id'];
                    $serialNumber = $data['batch_no'];
                    $remark = "序列号";
                    if (!empty($data['click_flag'])) {
                        $clickflag = $data['click_flag'];
                    }
                    $checkSerialInfo = SerialNumberModel::where([
                        'goods_id' => $data['goods_id'],
                        'serial_no' => $serialNumber,
                        'delete_flag' => 0
                    ])->first();
                    if (empty($checkSerialInfo)) {//如果是下级序列号不允许入库
                        return ['code' => 1, 'msg' => '该序列号没有找到，相应的商品信息！', 'data' => ''];
                    }
                    if (!empty($checkSerialInfo['parent_id'])) {//如果是下级序列号不允许入库
                        return ['code' => 1, 'msg' => '该商品作为套餐中的套件已被使用，请整件归库', 'data' => ''];
                    }
                }
                break;
            case 2://批次号
                return ['code' => 1, 'msg' => '批次号出库，正在维护中！', 'data' => ''];
                break;
            case 3://条形码
                if (!empty($data['batch_no'])) {
                    if (strpos($data['batch_no'], 'SMYCYJ') !== false) {
                        $code = explode('SMYCYJ', $data['batch_no']);
                        $mInfo = MaterielTypeModel::where([
                            'delete_flag' => 0,
                            'inventory_code' => $code,
                            'main_id' => $data['main_id']
                        ])->first();
                        if (empty($mInfo))
                            return ['code' => 1, 'msg' => '库存码（' . $code . '）无商品信息！', 'data' => ''];
                        $goodsId = $mInfo['id'];
                        $remark = "库存码";
                    } else {
                        $mInfo = MaterielTypeModel::where([
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0,
                            'bar_code' => $data['batch_no']
                        ])->first();

                        if (empty($mInfo)) {
                            $mList = MaterielTypeModel::where([
                                'main_id' => $data['main_id'],
                                'delete_flag' => 0
                            ])->where('number_prefix', '!=', '')->get()->toArray();

                            if (!empty($mList)) {
                                foreach ($mList as $val) {
                                    if (strpos($data['batch_no'], $val['number_prefix']) !== false) {
                                        $goodsId = $val['id'];
                                    }
                                }
                            }
                        }
                        if (empty($goodsId)) {
                            $barCode = $data['batch_no'];
                        }
                        $remark = "条形码";
                    }
                }
                break;
            /*  case 4://库位库存码
                $manageInfo = StorageManageModel::query()->where([
                    'id' => $data['batch_no'],
                    'delete_flag' =>0
                ])->first();
                if(empty($manageInfo))
                    return ['code'=>1,'msg'=>'库位库存码，无库存信息！','data'=>''];*/
            default:
                if (!empty($data['batch_no'])) {
                    $number = $data['batch_no'];//外部编号
                    $mList = MaterielTypeModel::where([
                        'a.main_id' => $data['main_id'],
                        'delete_flag' => 0
                    ])->where('number_prefix', '!=', '')->get();
                    if (!empty($mList)) {
                        foreach ($mList as $val) {
                            if (strpos($number, $val['number_prefix']) !== false) {
                                $goodsId = $val['id'];
                            }
                        }
                    }
                    if (empty($goodsId)) {
                        return ['code' => 1, 'msg' => '编码商品信息,不存在!', 'data' => ''];
                    }
                    $remark = "编号码";
                }
                break;
        }
        CommonService::log($remark . '-扫码入库', $data, $data['time']);
        $materielTypeInfo = MaterielsTypeModel::select(
            'a.id',
            'materiel_name',
            'type_name',
            'materiel_no',
            'b.id as materiel_class_id',
            'b.class_name',
            'b.class_no',
            'c.id as first_class',
            'cost',
            'a.is_use_serial',
            'a.is_product_materiel'
        )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id');
        /* if($data['code_type'] ==4){
                    $materielTypeInfo->where('a.id',StorageManageModel::query()
                        ->where(['id'=>$data['batch_no']])
                        ->value('type_id'));
                }else{*/
        if (!empty($goodsId)) {
            $materielTypeInfo->where('a.id', $goodsId);
        }
        if (!empty($barCode)) {
            $materielTypeInfo->where('a.bar_code', $barCode);
        }
        /*}*/
        $materielTypeInfo = $materielTypeInfo->where([
            'a.main_id' => $data['main_id'],
            'a.delete_flag' => 0,
            'b.delete_flag' => 0
        ])->first();

        if (empty($materielTypeInfo)) {
            return ['code' => 1, 'msg' => '物料' . $remark . '信息,不存在!', 'data' => ''];
        }

        //仓库信息
        $storageInfo = StorageModel::where([
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();

        //入库仓库信息
        /*$storageInfo = StorageModel::query()
            ->select(
                'a.id as storage_id',
                'b.id as shelf_id',
                'c.id as location_id',
                'storage_name',
                'shelf_name',
                'location_name',
                'storage_address',
            )->from('storage as a')
            ->leftJoin('storage_shelf as b','b.storage_id','=','a.id')
            ->leftJoin('storage_shelf_location as c','c.shelf_id','=','b.id')
            ->where([
                'a.id' => $data['storage_id'],
                'b.id' => $data['shelf_id'],
                'c.id' => $data['location_id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
                'b.status' => 1,
                'c.status' => 1
            ])->first();*/

        if (empty($storageInfo)) {
            return ['code' => 1, 'msg' => '你选择的仓库，不存在！', 'data' => ''];
        }
        /* if($data['code_type'] == 4){
            //检查库存信息
            $checkStorageManage = StorageManageModel::where([
                'id' => $data['batch_no'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->first();
        }else{*/
        //检查库存信息
        $checkStorageManage = StorageManageModel::where([
            'type_id' => $materielTypeInfo['id'],
            'storage_id' => $data['storage_id'],
            /* 'shelf_id' => $data['shelf_id'],
                'location_id' => $data['location_id'],*/
            'main_id' => $data['main_id'],
            'delete_flag' => 0
        ])->first();
        /*}*/
        if ($materielTypeInfo['is_use_serial'] == 1) {
            if (empty($serialNumber)) {
                return ['code' => 1, 'msg' => '商品' . $materielTypeInfo['materiel_name'] . '已开启序列号选项，请选择序列号入库', 'data' => ''];
            }

            if (!empty($checkSerialInfo)) {
                if ($checkSerialInfo['status'] == 0) {
                    if (empty($clickflag)) {
                        return ['code' => 1, 'msg' => '商品' . $materielTypeInfo['materiel_name'] . '中序列号' . $checkSerialInfo['serial_no'] . '已被使用是否再次入库？', 'data' => ''];
                    }
                } else {
                    return ['code' => 1, 'msg' => '商品' . $materielTypeInfo['materiel_name'] . '中序列号' . $checkSerialInfo['serial_no'] . '已存在', 'data' => ''];
                }
            } else {
                return ['code' => 1, 'msg' => '商品' . $materielTypeInfo['materiel_name'] . '没有序列号' . $serialNumber . '的信息', 'data' => ''];
            }
        }
        $newStorageManageInfo = [];//新物料入库
        $updateInStorageNum = [];//已有物料入库
        $cost = $materielTypeInfo['cost'];
        if (!empty($checkStorageManage)) {
            $cost = $checkStorageManage['materiel_mean_cost'];
        }
        if (empty($checkStorageManage)) {
            $sfData = ShelfService::get_default($data['storage_id']);
            $shelf_id = 0;
            $location_id = 0;

            if (!empty($sfData)) {
                $shelf_id = $sfData['id'];
                $lData = ShelfService::get_default($shelf_id, 2);
                $location_id = $lData['id'];
            }
            $newStorageManageInfo = [
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($materielTypeInfo['class_no']) ? '' : $materielTypeInfo['class_no'],//物料二级分类名称
                'type_id' => $materielTypeInfo['id'],//物料id
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                'materiel_no' => empty($materielTypeInfo['materiel_no']) ? '' : $materielTypeInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $cost ?? 0,
                'storage_id' => $storageInfo['id'],//仓库id
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' => 1,//采购单内物料商品入库数量
                //'virtual_storage_num' => 1,
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => $data['time'],//入库时间
                'alert_num' => 0,
                'created_at' => $data['time'],
                'shelf_id' => $shelf_id,
                'location_id' => $location_id,
            ];
        } else {
            $updateInStorageNum = [
                'id' => $checkStorageManage->id,
                'in_storage_num' => 1,
                'materiel_mean_cost' => $cost ?? 0,
            ];
            $shelf_id = $checkStorageManage['shelf_id'];
            $location_id = $checkStorageManage['location_id'];
        }
//        $sortFlag = 0;
        $inStorageNum = !empty($checkStorageManage) ? $checkStorageManage['in_storage_num'] : 0;
//            if(!empty($checkStorageManage['alert_num'])) {
//                if ($inStorageNum + 1 > $checkStorageManage['alert_num']) {
//                    $sortFlag = 0;
//                }else{
//                    $sortFlag=1;
//                }
//            }
        //入库操作记录
        $logInStorage = [
            'type' => 4,//日志类型;0:入库;1:调拨入库;2:直接入库;4扫码入库
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($materielTypeInfo['class_no']) ? '' : $materielTypeInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $materielTypeInfo['id'],//物料id
            'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
            'type_name' => $materielTypeInfo['type_name'],//物料型号名称
            'materiel_no' => empty($materielTypeInfo['materiel_no']) ? '' : $materielTypeInfo['materiel_no'],//物料编号
            'operate_num' => 1,//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + 1,//操作后库存数
            'materiel_mean_cost' => $cost ?? 0,//物料均价
            'in_storage_time' => $data['time'],//入库时间
            'remark' => "",//备注
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => $data['time'],
            'serial_number' => !empty($serialNumber) ? $serialNumber : '',
            'shelf_id' => $shelf_id,
            'location_id' => $location_id
        ];

        DB::beginTransaction();
        try {
            $meanCost = 0;
            if (!empty($newStorageManageInfo)) {
                $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
            }

            if (!empty($updateInStorageNum)) {
                StorageManageModel::where('id', $updateInStorageNum['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + 1'),
                        //'virtual_storage_num' => DB::raw('virtual_storage_num + 1'),
                        'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
//                        'sort_flag'=>$sortFlag
                    ]);

                $meanCost = $updateInStorageNum['materiel_mean_cost'];
                $newStorageManageId = $updateInStorageNum['id'];
            }

            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';

            do {
                $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            } while (!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageManageId,
                'batch_num' => 1,
                'batch_left_num' => 1,
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => $data['time']
            ]);

            $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

            $inLogId = LogInstorageModel::query()->insertGetId($logInStorage);

            if (!empty($serialNumber)) {
                if (!empty($clickflag) && !empty($checkSerialInfo)) {

                    SerialNumberModel::where([
                        'goods_id' => $materielTypeInfo['id'],
                        'serial_no' => $serialNumber,
                        'delete_flag' => 0
                    ])->update([
                        'status' => 1,
                        'storage_manage_id' => $newStorageManageId
                    ]);
                    if ($materielTypeInfo['is_product_materiel'] == 1) {
                        SerialNumberModel::where([
                            'parent_id' => $checkSerialInfo['id'],
                            'delete_flag' => 0
                        ])->update(['status' => 1]);
                    }

                }
            }
            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                1,
                $inStorageNum + 1,
                $inLogId
            );
            CommonService::cancelAlertFlag($data['main_id']);
            $logData = '商品名称：' . $materielTypeInfo['materiel_name'] . '入库数量 1,仓库名：' . $storageInfo['storage_name'];
            CommonService::operateResult($data['user_id'], $data['time'], $data, $logData);
            DB::commit();
            if (!empty($materielTypeInfo)) {
                return ['code' => 0, 'msg' => 'success', 'data' => '商品（' . $materielTypeInfo['materiel_name'] . '），入库成功！'];
            } else {
                return ['code' => 0, 'msg' => 'success', 'data' => '入库成功！'];
            }
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug($remark . '扫码入库' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $remark . '扫码，入库失败！', 'data' => ''];
        }
    }

    //直接出库
    static public function directOutStorage($data)
    {
        //需出库物料信息
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.storage_id',
            'a.materiel_class_id',
            'a.type_id',
            'a.in_storage_num',
            'a.materiel_mean_cost',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.storage_name',
            'd.storage_address',
            'a.alert_num',
            'a.virtual_storage_num',
            'c.selling_price'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->where([
                'a.id' => $data['id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0
            ])->first();

        if (empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
        }
        if (!OperMainAccountModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'delete_flag' => 0
            ])->exists()) {
            if ($storageManageInfo['in_storage_num'] < $data['num']) {
                return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:' . $storageManageInfo['in_storage_num'], 'data' => ''];
            }
        }

        //调出货架信息
        if (empty($data['location_id'])) {
            //获取货架
            $shelfInfo = StorageShelfModel::where([
                'storage_id' => $storageManageInfo['storage_id'],
                'shelf_type' => 1
            ])->first();

            $data['shelf_id'] = $shelfInfo['id'];

            //获取库位
            $locationInfo = StorageShelfLocationModel::where([
                'shelf_id' => $shelfInfo['id'],
                'location_type' => 1
            ])
                ->first();

            $data['location_id'] = $locationInfo['id'];
        }

        DB::beginTransaction();

        try {
            //出库操作记录日志
            $logId = LogOutstorageModel::query()->insertGetId([
                'type' => 2,//type;0:出库;1:调出;2:直接出库;
                'storage_id' => $storageManageInfo['storage_id'],
                'storage_name' => $storageManageInfo['storage_name'],
                'storage_address' => $storageManageInfo['storage_address'],
                'next_storage_id' => 0,
                'next_storage_name' => '',
                'next_storage_address' => '',
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['num'],
                'last_storage_num' => $storageManageInfo['in_storage_num'],
                'next_storage_num' => $storageManageInfo['in_storage_num'] - $data['num'],
                'sell_price' => $storageManageInfo['selling_price'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark']) ? '' : $data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => time(),
                'created_at' => time(),
                'shelf_id' => $data['shelf_id'],
                'location_id' => $data['location_id'],
                'label_id' => $data['label_id'],
                'label_name' => !empty($data['label_name']) ? $data['label_name'] : '',
            ]);

            /*if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$data['num'])
                    ]);
            }
            else {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                    ]);
            }*/

            StorageManageModel::where('id', $data['id'])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num - ' . $data['num']),
                    //'virtual_storage_num' => DB::raw('virtual_storage_num - '.$data['num'])
                ]);

            MessageService::sendAlertSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $storageManageInfo['alert_num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data['num']
            );

            MessageService::sendShortSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $data,
                $storageManageInfo['storage_name'],
                $storageManageInfo['storage_id']
            );

            MessageService::sendOutSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'],
                $storageManageInfo['storage_name'],
                $data['num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['alert_num'],
                $logId
            );
            $logData = '商品名称：' . $storageManageInfo['materiel_name'] . '（' . $storageManageInfo['materiel_no'] . '）' .
                '出库数量：' . $data['num'] . ' 仓库名：' . $storageManageInfo['storage_name'];
            CommonService::operateResult($data['user_id'], $data['time'], $storageManageInfo, $logData);
            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('直接出库异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];
        }
    }

    static public function setAlertNum($data)
    {
        $storageManageInfo = StorageManageModel::where([
            'id' => $data['id'],
            'main_id' => $data['main_id']
        ])->first();

        if (empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '目标库存不存在，无法完成预警数设置', 'data' => ''];
        }

        if ($storageManageInfo['delete_flag']) {
            return ['code' => 1, 'msg' => '目标库存不存在，无法完成预警数设置', 'data' => ''];
        }

//        $sortFlag = 0;
//        if($data['alert_num'] != 0) {
//            if($data['alert_num'] > $storageManageInfo['in_storage_num']) {
//                $sortFlag = 1;
//            }
//        }

        StorageManageModel::where('id', $data['id'])->update([
            'alert_num' => $data['alert_num'],
//            'sort_flag' => $sortFlag
        ]);
        CommonService::setAlertFlag($data['main_id']);
        CommonService::cancelAlertFlag($data['main_id']);
        $logData = '商品名称：' . $storageManageInfo['materiel_name'] . '（' . $storageManageInfo['materiel_no'] . '）' .
            '设置的预警数量：' . $data['alert_num'] . ' 仓库名：' . $storageManageInfo['storage_name'];
        CommonService::operateResult($data['user_id'], $data['logTime'], $data, $logData);
        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    public static function exportData(array $user, $data)
    {
        $condition = [];

        $keyword = empty($data['keyword']) ? '' : $data['keyword'];

//        if(!empty($data['f_class_id'])) {
//            $condition['c.id'] = ['EQ' => $data['f_class_id']];
//        }

        if (!empty($data['s_class_id'])) {
            $condition['a.materiel_class_id'] = ['EQ' => $data['s_class_id']];
        }

        if (!empty($data['storage_id'])) {
            $condition['a.storage_id'] = ['EQ' => $data['storage_id']];
        }

        $query = StorageManageModel::select(
            'a.id',
            'd.materiel_name',
            'a.type_id',
            'd.type_name',
            'd.materiel_no',
            'a.materiel_mean_cost',
            'a.storage_id',
            'e.storage_name',
            'e.storage_address',
            'a.in_storage_num',
            'a.alert_num',
            'c.id as f_class_id',
            'c.class_name as f_class_name',
            'c.class_no as f_class_no',
            'b.id as s_class_id',
            'b.class_name as s_class_name',
            'b.class_no as s_class_no',
            'd.materiel_img',
            'd.remark',
            'd.bar_code',
            'd.is_use_serial',
            'd.selling_price',
            'd.lower_selling_price',
            'd.materiel_unit'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_class as b', 'a.materiel_class_id', '=', 'b.id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
            ->leftJoin('materiel_type as d', 'd.id', '=', 'a.type_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->where($condition)
            ->where('a.delete_flag', 0)
            ->where($user)
            ->where(function ($query) use ($keyword) {
                $query->orWhere('d.materiel_name', 'like', '%' . $keyword . '%')
                    ->orWhere('d.type_name', 'like', '%' . $keyword . '%')
                    ->orWhere('d.materiel_no', 'like', '%' . $keyword . '%')
                    ->orWhere('b.class_no', 'like', '%' . $keyword . '%');
            });

//        if(!empty($data['class_no'])) {
//            $keyword = empty($data['class_no'])?'':$data['class_no'];
//
//            $query->where(function($query) use ($keyword) {
//                $query->orWhere('b.class_no', 'like', '%'.$keyword.'%');
//                $query->orWhere('c.class_no', 'like', '%'.$keyword.'%');
//            });
//        }
//
//        if(!empty($data['max_mean_cost']) && !empty($data['min_mean_cost'])) {
//            $query->whereBetween('a.materiel_mean_cost', [$data['min_mean_cost'], $data['max_mean_cost']]);
//        }
//        else if(!empty($data['max_mean_cost']) && empty($data['min_mean_cost'])) {
//            $query->where('a.materiel_mean_cost', '<=', $data['max_mean_cost']);
//        }
//        else if(empty($data['max_mean_cost']) && !empty($data['min_mean_cost'])) {
//            $query->where('a.materiel_mean_cost', '>=', $data['min_mean_cost']);
//        }
//        //
//        if(!empty($data['max_storage_num']) && !empty($data['min_storage_num'])) {
//            $query->whereBetween('a.in_storage_num', [$data['min_storage_num'], $data['max_storage_num']]);
//        }
//        else if(!empty($data['max_storage_num']) && empty($data['min_storage_num'])) {
//            $query->where('a.in_storage_num', '<=', $data['max_storage_num']);
//        }
//        else if(empty($data['max_storage_num']) && !empty($data['min_storage_num'])) {
//            $query->where('a.in_storage_num', '>=', $data['min_storage_num']);
//        }

        return $query->orderBy('a.materiel_no')
            ->get()->toArray();
    }

    private static function clearLog($data)
    {
        LogInStorageModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);

        LogOutStorageModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);

        LogPackageModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);
        TallyModel::where('main_id', $data['main_id'])
            ->update(['delete_flag' => 1]);
        return true;
    }

    public static function detail(array $data)
    {
        $result = StorageManageModel::detail($data);

        if (!empty($result['materiel_img'])) {
            $materielImg = array_filter(explode(',', $result['materiel_img']), function ($v) {
                return $v !== '';
            });

            $result['materiel_img'] = $materielImg[0];
        }

        if ($result['is_product_materiel']) {
            $productContent = MaterielProductContentModel::select(
                'a.type_id',
                'a.num',
                'b.materiel_name',
                'b.materiel_no',
                'b.materiel_img',
                'b.type_name',
                'b.is_use_serial'
            )
                ->from('materiel_product_content as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                ->where('product_id', $result['type_id'])
                ->get()->toArray();

            foreach ($productContent as &$value) {
                if (!empty($value['materiel_img'])) {
                    $materielImg = array_filter(explode(',', $value['materiel_img']), function ($v) {
                        return $v !== '';
                    });

                    $value['materiel_img'] = $materielImg[0];
                }

                $value['content_bind_num'] = SerialNumberModel::query()->where([
                    'package_id' => $result['type_id'],
                    'goods_id' => $value['type_id'],
                    'package_storage_id' => $result['id'],
                    'status' => 1,
                    'delete_flag' => 0
                ])->count();
            }

            $result['product_content'] = $productContent;
        } else {
            $result['product_content'] = [];
        }

        return $result;
    }

    public static function usedSerialList(array $data)
    {
        $typeId = array_filter(explode(',', $data['type_id']), function ($v) {
            return $v !== '';
        });

        $serialInfo = SerialNumberModel::select(
            'id',
            'serial_no',
            'goods_id as type_id',
            'storage_manage_id'
        )->where([
            'status' => 0,
            'delete_flag' => 0
        ])
            ->whereIn('goods_id', $typeId)
            ->get()->toArray();

        $result = [];
        foreach ($serialInfo as $key => $value) {
            $materialInfo = MaterielTypeModel::where('id', $value['type_id'])->first();
            $result[$value['type_id']]['type_id'] = $value['type_id'];
            $result[$value['type_id']]['materiel_name'] = $materialInfo['materiel_name'];
            $result[$value['type_id']]['type_name'] = $materialInfo['type_name'];
            $result[$value['type_id']]['serial_info'][] = $value;
        }

        return array_values($result);
    }

    public static function handleReturnPackageStore($data)
    {
        //get storage_manage info
        $storageManageInfo = StorageManageModel::select(
            'a.in_storage_num',
            'a.type_id',
            'b.materiel_name',
            'b.type_name',
            'b.cost',
            'a.storage_id',
            'c.storage_name',
            'c.storage_address',
            'b.is_product_materiel',
            'b.is_use_serial',
            'b.materiel_unit',
            'a.virtual_storage_num',
            'd.id as class_id',
            'd.class_name',
            'd.class_no',
            'd.class_no',
            'b.selling_price',
            'a.shelf_id',
            'a.location_id'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('storage as c', 'c.id', '=', 'a.storage_id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'b.materiel_class_id')
            ->where([
                'a.id' => $data['storage_manage_id'],
                'a.main_id' => $data['main_id']
            ])
            ->first();

        if (empty($storageManageInfo) || $storageManageInfo['delete_flag']) {
            return ['code' => 1, 'msg' => '套件返仓的目标库存不存在', 'data' => ''];
        }

        if (!$storageManageInfo['is_product_materiel']) {
            return ['code' => 1, 'msg' => '目标库存对应内容不是套餐，无法返仓', 'data' => ''];
        }

        /* if(($storageManageInfo['virtual_storage_num'] - $data['product_num']) < 0){
            return ['code'=>1,'msg'=>'套餐'.$storageManageInfo['materiel_name'].'虚拟库存数量X'.$storageManageInfo['virtual_storage_num'].'不足!','data'=>''];

        }*/

        if ($storageManageInfo['in_storage_num'] < $data['product_num']) {
            return ['code' => 1,
                'msg' => '套件返仓可操作库存数X' . $storageManageInfo['in_storage_num'] . $storageManageInfo['materiel_unit'] . '已超出X' . ($data['product_num'] - $storageManageInfo['in_storage_num']) . $storageManageInfo['materiel_unit'],
                'data' => ''
            ];
        }

        //返仓的套餐序列号
        $productContentBindSerialNo = [];//套餐序列号对应的组件序列号
        $productContentBindSerialId = [];//套餐序列号对应的组件序列号id
        $productContentSelectSerialNo = [];//套件返仓选取的序列号信息
        $productSerialId = [];//套餐序列号id信息
        if (!empty($data['product_serial_id'])) {
            $productSerialId = array_filter(explode(',', $data['product_serial_id']), function ($v) {
                return $v !== '';
            });

            $productContentBindSerialNo = SerialNumberModel::where(['delete_flag' => 0])
                ->whereIn('parent_id', $productSerialId)
                ->pluck('serial_no')->toArray();

            $productContentBindSerialId = SerialNumberModel::where(['delete_flag' => 0])
                ->whereIn('parent_id', $productSerialId)
                ->pluck('id')->toArray();
        }

        $logOutData = [
            'type' => 5,
            'materiel_type_id' => $storageManageInfo->type_id,
            'materiel_name' => $storageManageInfo->materiel_name,
            'type_name' => empty($storageManageInfo->type_name) ? '' : $storageManageInfo->type_name,
            'materiel_no' => empty($storageManageInfo->materiel_no) ? '' : $storageManageInfo->materiel_no,
            'storage_id' => $storageManageInfo->storage_id,
            'storage_name' => $storageManageInfo->storage_name,
            'storage_address' => empty($storageManageInfo->storage_address) ? '' : $storageManageInfo->storage_address,
            'curr_storage_manage_id' => $data['storage_manage_id'],
            'materiel_class_id' => $storageManageInfo->class_id,
            'materiel_class_name' => $storageManageInfo->class_name,
            'materiel_class_no' => empty($storageManageInfo->class_no) ? '' : $storageManageInfo->class_no,
            'operate_num' => $data['product_num'],
            'last_storage_num' => $storageManageInfo->in_storage_num,
            'next_storage_num' => $storageManageInfo->in_storage_num - $data['product_num'],
            'sell_price' => $storageManageInfo->selling_price,
            'materiel_mean_cost' => $storageManageInfo->cost,
            'serial_number' => implode(',', $productContentBindSerialNo),
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'out_storage_time' => empty($data['in_storage_time']) ? $data['time'] : strtotime($data['in_storage_time']),
            'shelf_id' => $storageManageInfo->shelf_id,
            'location_id' => $storageManageInfo->location_id,
            'label_id' => empty($data['label_id']) ? 0 : $data['label_id'],
            'label_name' => empty($data['label_name']) ? '' : $data['label_name'],
            'created_at' => $data['time']
        ];

        $productContent = json_decode($data['product_content'], true);

        if (empty($productContent)) {
            return ['code' => 1, 'msg' => '请填写要返仓的组件信息', 'data' => ''];
        }

        DB::beginTransaction();

        try {
            $addSerialInsert = [];//手动新建的序列号-不存在
            $addSerialUpdate = [];//手动新建的序列号-已存在
            $materielContentStorageUpdate = [];//已存在的组件库存-更新
            $logData = [];
            $serialId = [];//返仓选择的序列号id
            foreach ($productContent as $value) {
                //商品信息
                $materielContentInfo = MaterielTypeModel::query()->select(
                    'a.id as type_id',
                    'a.materiel_name',
                    'a.type_name',
                    'a.materiel_no',
                    'a.cost',
                    'b.id as class_id',
                    'b.class_name',
                    'a.is_use_serial',
                    'b.class_no'
                )
                    ->from('materiel_type as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->where('a.id', $value['type_id'])->first();

                //仓库信息
                $storageInfo = StorageModel::query()->where('id', $value['storage_id'])->first();

                //获得货架及库位信息
                if (empty($value['location_id'])) {
                    //货架信息
                    $shelfInfo = StorageShelfModel::where('storage_id', $value['storage_id'])->where('shelf_type', 1)->first();
                    //库位信息
                    $locationInfo = StorageShelfLocationModel::where([
                        'shelf_id' => $shelfInfo['id'],
                        'location_type' => 1
                    ])->first();

                    $shelfId = $shelfInfo['id'];
                    $locationId = $locationInfo['id'];
                } else {
                    $shelfId = $value['shelf_id'];
                    $locationId = $value['location_id'];
                }

                //获取组件库存信息
                $getStorageManageInfo = StorageManageModel::query()->where([
                    'type_id' => $value['type_id'],
                    'storage_id' => $value['storage_id'],
                    'main_id' => $data['main_id'],
                    'delete_flag' => 0
                ])
                    ->first();

                //组件首次入库
                if (empty($getStorageManageInfo)) {
                    $storageManageId = StorageManageModel::query()->insertGetId([
                        'materiel_class_id' => $materielContentInfo->class_id,
                        'materiel_class_name' => $materielContentInfo->class_name,
                        'materiel_class_no' => $materielContentInfo->class_no,
                        'type_id' => $materielContentInfo->type_id,
                        'materiel_name' => $materielContentInfo->materiel_name,
                        'type_name' => !empty($materielContentInfo->type_name) ? $materielContentInfo->type_name : "",
                        'materiel_no' => !empty($materielContentInfo->materiel_no) ? $materielContentInfo->materiel_no : "",
                        'materiel_mean_cost' => !empty($materielContentInfo->cost) ? $materielContentInfo->cost : 0,
                        'storage_id' => $storageInfo->id,
                        'storage_name' => $storageInfo->storage_name,
                        'storage_address' => !empty($storageInfo->storage_address) ? $storageInfo->storage_address : "",
                        'in_storage_num' => $value['num'],
                        'virtual_storage_num' => $value['num'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => empty($data['in_storage_time']) ? $data['time'] : strtotime($data['in_storage_time']),
                        'shelf_id' => $shelfId,
                        'location_id' => $locationId,
                        'created_at' => $data['time'],
                    ]);

                    $lastNum = 0;//操作前数量
                    $nextNum = $value['num'];//操作后数量
                } else {
                    $lastNum = $getStorageManageInfo->in_storage_num;//操作前数量
                    $nextNum = $getStorageManageInfo->in_storage_num + $value['num'];//操作后数量

                    $materielContentStorageUpdate[] = [
                        'id' => $getStorageManageInfo->id,
                        'in_storage_num' => $getStorageManageInfo->in_storage_num + $value['num'],
                        'virtual_storage_num' => $getStorageManageInfo->virtual_storage_num + $value['num'],
                    ];

                    $storageManageId = $getStorageManageInfo->id;
                }

                if ($materielContentInfo['is_use_serial'] && empty($value['serial_info'])) {
                    throw new Exception('套餐组件:' . $materielContentInfo['materiel_name'] . '已开启序列号，请选择序列号后重试');
                }

                $serialNumberStr = '';
                if ($materielContentInfo['is_use_serial']) {
                    if ($value['num'] != count($value['serial_info'])) {
                        throw new Exception('套餐组件:' . $materielContentInfo['materiel_name'] . '返仓数量与已选择的序列号数量不一致，请重试');
                    }

                    foreach ($value['serial_info'] as $serialValue) {
                        $productContentSelectSerialNo[] = $serialValue['serial_no'];
                        $serialNumberStr .= $serialValue['serial_no'] . ',';
                        if ($serialValue['serial_id'] == 0) {//手动添加的序列号
                            $serialInfo = SerialNumberModel::query()->where([
                                'goods_id' => $value['type_id'],
                                'serial_no' => $serialValue['serial_no'],
                                'delete_flag' => 0
                            ])->first();

                            if (!empty($serialInfo)) {
                                throw new Exception('套餐组件:' . $materielContentInfo['materiel_name'] . '返仓序列号:' . $serialValue['serial_no'] . '已存在，请重试');
                            }

                            $addSerialInsert = [
                                'goods_id' => $value['type_id'],
                                'storage_manage_id' => $storageManageId,
                                'serial_no' => $serialValue['serial_no'],
                                'status' => 1,
                                'main_id' => $data['main_id'],
                                'created_at' => $data['time'],
                            ];
                            $serId = SerialNumberModel::insertGetId($addSerialInsert);
                            $serialId[] = $serId;
                            //2023-04-12 注释
//                            if(empty($serialInfo)) {
//                                $addSerialInsert[] = [
//                                    'goods_id' => $value['type_id'],
//                                    'storage_manage_id' => $storageManageId,
//                                    'serial_no' => $serialValue['serial_no'],
//                                    'status' => 1,
//                                    'main_id' => $data['main_id'],
//                                    'created_at' => $data['time'],
//                                ];
//                            }
//                            else {
//                                if($serialInfo['parent_id'] == 0) {
//                                    throw new Exception('套餐组件:'.$materielContentInfo['materiel_name'].'返仓序列号:'.$serialValue['serial_no'].'已存在，请重试');
//                                }
//
//                                $addSerialUpdate[] = [
//                                    'id' => $serialInfo['id'],
//                                    'storage_manage_id' => $storageManageId,
//                                    'parent_id' => 0,
//                                    'package_storage_id' => 0,
//                                    'package_id' => 0,
//                                ];
//                            }
                        } else {//选择的序列号
                            $serialInfo = SerialNumberModel::query()->where([
                                'goods_id' => $value['type_id'],
                                'id' => $serialValue['serial_id'],
                                'delete_flag' => 0
                            ])->first();
                            $serialId[] = $serialValue['serial_id'];
                            if (!$serialInfo['status']) {
                                throw new Exception('套餐组件:' . $materielContentInfo['materiel_name'] . '返仓序列号:' . $serialValue['serial_no'] . '已被使用，请重试');
                            }

                            $addSerialUpdate[] = [
                                'id' => $serialInfo['id'],
                                'parent_id' => 0,
                                'storage_manage_id' => $storageManageId,
                                'package_storage_id' => 0,
                                'package_id' => 0,
                            ];

//                            if(empty($serialInfo)) {
//                                $addSerialInsert[] = [
//                                    'goods_id' => $value['type_id'],
//                                    'storage_manage_id' => $storageManageId,
//                                    'serial_no' => $serialValue['serial_no'],
//                                    'status' => 1,
//                                    'main_id' => $data['main_id'],
//                                    'created_at' => $data['time'],
//                                ];
//                            }
//                            else {
//                                if($serialInfo['parent_id'] == 0) {
//                                    throw new Exception('套餐组件:'.$materielContentInfo['materiel_name'].'返仓序列号:'.$serialValue['serial_no'].'已存在，请重试');
//                                }
//
//                                $addSerialUpdate[] = [
//                                    'id' => $serialInfo['id'],
//                                    'parent_id' => 0,
//                                    'package_storage_id' => 0,
//                                    'package_id' => 0,
//                                ];
//                            }
                        }
                        /* $serialId[] = $serialValue['serial_id']; */
                    }
                }

                $logData[] = [
                    'type' => 5,
                    'curr_storage_manage_id' => $storageManageId,
                    'storage_id' => $storageInfo->id,
                    'storage_name' => $storageInfo->storage_name,
                    'storage_address' => !empty($storageInfo->storage_address) ? $storageInfo->storage_address : "",
                    'materiel_class_id' => $materielContentInfo->class_id,
                    'materiel_class_name' => $materielContentInfo->class_name,
                    'materiel_class_no' => $materielContentInfo->class_no,
                    'materiel_type_id' => $materielContentInfo->type_id,
                    'materiel_name' => $materielContentInfo->materiel_name,
                    'type_name' => !empty($materielContentInfo->type_name) ? $materielContentInfo->type_name : "",
                    'materiel_no' => !empty($materielContentInfo->materiel_no) ? $materielContentInfo->materiel_no : "",
                    /* 'purchase_no' => $productInfo['product_no'], */
                    'operate_num' => $value['num'],
                    'last_storage_num' => $lastNum,
                    'next_storage_num' => $nextNum,
                    'materiel_mean_cost' => $materielContentInfo->cost,
                    'serial_number' => empty($serialNumberStr) ? '' : substr($serialNumberStr, 0, -1),
                    'all_id_type' => 6,
                    'all_id' => $data['product_id'],
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'in_storage_time' => strtotime($data['in_storage_time']),
                    'created_at' => time(),
                    'shelf_id' => $shelfId,
                    'remark' => empty($value['remark']) ? '' : $value['remark'],
                    'location_id' => $locationId,
                ];
            }

            /**
             * 按套餐序列号返仓-校验添加的序列号是否存在不属于该套餐的情况
             * 删除返仓的套餐序列号
             */
            if (!empty($productContentBindSerialId)) {
                if (empty($serialId)) {
                    throw new Exception('请选择套件返仓序列号对应的序列号');
                } else {
                    if (count($productContentBindSerialId) != count($serialId)) {
                        throw new Exception('套件返仓选择的序列号数量(X' . count($serialId) . ')与返仓所要求的数量(X' . count($productContentBindSerialId) . ')不符，请重试');
                    }

                    foreach ($serialId as $selectValue) {
                        if (!in_array($selectValue, $productContentBindSerialId, true)) {
                            throw new Exception('套餐组件添加的序列号:' . $selectValue . '未被套餐绑定,请重试');
                        }
                    }
                }
            }

            /* if(!empty($addSerialInsert)) {
                SerialNumberModel::insert($addSerialInsert);
            } */

            if (!empty($addSerialUpdate)) {
                batch()->update(new SerialNumberModel, $addSerialUpdate, 'id');
            }

            if (!empty($materielContentStorageUpdate)) {
                batch()->update(new StorageManageModel, $materielContentStorageUpdate, 'id');
            }

            $logOutId = 0;
            if (!empty($logOutData)) {
                $logOutId = LogOutStorageModel::query()->insertGetId($logOutData);
            }

            if (!empty($logData)) {
                foreach ($logData as &$logValue) {
                    $logValue['log_out_id'] = $logOutId;
                }

                LogInStorageModel::query()->insert($logData);
            }

            if (!empty($productSerialId)) {
                SerialNumberModel::query()->whereIn('id', $productSerialId)->update(['delete_flag' => 1]);
            }

            StorageManageModel::query()->where('id', $data['storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num - ' . $data['product_num']),
                    'virtual_storage_num' => DB::raw("virtual_storage_num - " . $data['product_num']),
                ]);

            CommonService::setAlertFlag($data['main_id']);
            CommonService::cancelAlertFlag($data['main_id']);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('套件返仓异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     * 处理套件返仓数据
     * @param type_id    商品id
     * @param storage_id 仓库id
     * @param num        返仓数量
     * @param remark     备注
     * @param serial_info 序列号信息（开启了序列号，传相应数据）
     * @param serial_id   序列号id
     * @param storage_manage_id 库存id
     * @param num               序列号数量
     */
    public static function handleReturnPackageStore2($data)
    {
        $smId = 0;
        $smCondition = [];
        $logData = [];
        //查询套餐库存信息
        $productStorageManageInfo = StorageManageModel::where([
            'id' => $data['storage_manage_id'],
            'type_id' => $data['product_id'],
            'is_product_materiel' => 1,
            'delete_flag' => 0
        ])->first();

        if (empty($productStorageManageInfo))
            return ['code' => 1, 'msg' => '没有找到，套餐' . $productStorageManageInfo['materiel_name'] . '库存信息！', 'data' => ''];

        if (!is_numeric($data['product_num']) || $data['product_num'] < 0) {
            return ['code' => 1, 'msg' => '套餐' . $productStorageManageInfo['materiel_name'] . '返仓数量仅能为数字且必须大于0', 'data' => ''];
        }
        if ($productStorageManageInfo['in_storage_num'] - $data['product_num'] < 0) {
            return ['code' => 1, 'msg' => '套餐' . $productStorageManageInfo['materiel_name'] . '库存数量不足！', 'data' => ''];
        }

        if ($productStorageManageInfo['virtual_storage_num'] - $data['product_num'] < 0) {
            return ['code' => 1, 'msg' => '套餐' . $productStorageManageInfo['materiel_name'] . '虚拟库存数量不足！', 'data' => ''];

        }
        $productContent = json_decode($data['product_content'], true);

        if (!empty($productContent)) {
            DB::beginTransaction();
            try {
                //直接入库套餐序列号返仓
                $productContentBindSerialId = [];//套餐序列号对应的组件序列号
                $productContentSerialId = [];//组件返仓选择的序列号id
                if (!empty($data['product_serial_id'])) {
                    $productSerialId = array_filter(explode(',', $data['product_serial_id']), function ($v) {
                        return $v !== '';
                    });
                    $productContentBindSerialId = SerialNumberModel::where(['delete_flag' => 0])
                        ->whereIn('parent_id', $productSerialId)
                        ->pluck('serial_no')->toArray();
                    SerialNumberModel::query()->whereIn('id', $productSerialId)->update(['delete_flag' => 1]);
                }

                foreach ($productContent as $key => $val) {
                    //查询组件中的商品信息
                    $productInfo = MaterielProductContentModel::select('a.num', 'b.*')
                        ->from("materiel_product_content as a")
                        ->leftJoin('materiel_type as b', 'a.type_id', '=', 'b.id')
                        ->where('a.product_id', $data['product_id'])
                        ->where('b.id', $val['type_id'])
                        ->where('a.delete_flag', 0)
                        ->where('b.delete_flag', 0)
                        ->first();
                    if (empty($productInfo))
                        return ['code' => 1, 'msg' => '没有找到，商品' . $productInfo['materiel_name'] . '的信息', 'data' => ''];

                    /* DB::enableQueryLog(); */
                    //查询默认仓库和货架信息
                    if (empty($val['shelf_id']) || empty($val['location_id'])) {

                        $storageInfo = StorageModel::select('a.*', 'b.id as shelf_id', 'c.id as location_id')->from('storage as a')
                            ->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
                            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
                            ->where('a.id', $val['storage_id'])
                            ->where('a.delete_flag', 0)
                            ->where('b.status', 1)
                            ->where('c.location_type', 1)
                            ->where('b.shelf_type', 1)
                            ->first();

                    } else {
                        $storageInfo = StorageModel::select('a.*', 'b.id as shelf_id', 'c.id as location_id')->from('storage as a')
                            ->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
                            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
                            ->where('a.id', $val['storage_id'])
                            ->where('b.id', $val['shelf_id'])
                            ->where('c.id', $val['location_id'])
                            ->where('a.delete_flag', 0)
                            ->where('b.status', 1)
                            ->first();

                    }
                    /* echo "<pre>";
                   var_dump($storageInfo);die; */
                    if (empty($storageInfo))
                        return ['code' => 1, 'msg' => '没有找到，商品' . $productInfo['materiel_name'] . '选择的仓库信息', 'data' => ''];
                    $mcInfo = MaterielClassModel::select('id', 'class_name', 'class_no')
                        ->where(['delete_flag' => 0, 'id' => $productInfo['materiel_class_id']])->first();

                    //查询库存信息的条件
                    $smCondition = [
                        'type_id' => $val['type_id'],
                        'storage_id' => $val['storage_id'],
                        'delete_flag' => 0
                    ];
                    //DB::enableQueryLog();
                    //查询库存信息
                    $smInfo = StorageManageModel::where($smCondition)->first();

                    //判断商品仓库对应的库存是否存在，存在就修改在库数量和虚拟数量，不存在就新增库存信息
                    if (!empty($smInfo)) {//有商品库存信息
                        StorageManageModel::where('id', $smInfo['id'])->update([
                            'in_storage_num' => $smInfo['in_storage_num'] + $val['num'],
                            'virtual_storage_num' => $smInfo['virtual_storage_num'] + $val['num']
                        ]);

                        $storageManageId = $smInfo['id'];

                    } else {//没有商品库存信息

                        $smId = StorageManageModel::insertGetId([
                            'materiel_class_id' => !empty($mcInfo['id']) ? $mcInfo['id'] : 0,
                            'materiel_class_name' => !empty($mcInfo['materiel_class_name']) ? $mcInfo['materiel_class_name'] : "",
                            'materiel_class_no' => !empty($mcInfo['materiel_class_no']) ? $mcInfo['materiel_class_no'] : "",
                            'type_id' => $val['type_id'],
                            'materiel_name' => !empty($productInfo['materiel_name']) ? $productInfo['materiel_name'] : "",
                            'type_name' => !empty($productInfo['type_name']) ? $productInfo['type_name'] : "",
                            'materiel_no' => !empty($productInfo['materiel_no']) ? $productInfo['materiel_no'] : "",
                            'materiel_mean_cost' => !empty($productInfo['cost']) ? $productInfo['cost'] : "",
                            'storage_id' => $storageInfo['id'],
                            'storage_name' => !empty($storageInfo['storage_name']) ? $storageInfo['storage_name'] : "",
                            'storage_address' => !empty($storageInfo['storage_address']) ? $storageInfo['storage_address'] : "",
                            'in_storage_num' => $val['num'],
                            'virtual_storage_num' => $val['num'],
                            'main_id' => $data['main_id'],
                            'in_storage_time' => strtotime($data['in_storage_time']),
                            'shelf_id' => !empty($storageInfo['shelf_id']) ? $storageInfo['shelf_id'] : 0,
                            'location_id' => !empty($storageInfo['location_id']) ? $storageInfo['location_id'] : 0,
                            'created_at' => time(),
                        ]);

                        $storageManageId = $smId;

                    }
                    $serialNumberList = "";
                    //开启序列号商品相关操作
                    if ($productInfo['is_use_serial'] == 1) {//开启序列号
                        if (!empty($val['serial_info'])) {
                            $serialNum = 0;
                            /* echo "<pre>";
                            var_dump($val['serial_info']);die; */
                            foreach ($val['serial_info'] as $sKey => $sVal) {
                                //检查添加的序列号是否不属于被绑定的套餐序列号
                                if (!empty($productContentBindSerialId)) {
                                    if (!in_array($sVal['serial_no'], $productContentBindSerialId)) {
                                        throw new Exception('商品:' . $productStorageManageInfo['materiel_name'] . '选择的序列号:' . $sVal['serial_no'] . '不属于此套餐绑定的序列号');
                                    } else {
                                        $serialNumberInfo = SerialNumberModel::where([
                                            'storage_manage_id' => $storageManageId,
                                            'serial_no' => $sVal['serial_no'],
                                            'delete_flag' => 0
                                        ])->first();

                                        if (!$serialNumberInfo->status) {
                                            throw new Exception('商品:' . $productStorageManageInfo['materiel_name'] . '添加的序列号:' . $sVal['serial_no'] . '已被使用，无法返仓');
                                        }

                                        $serialNumberInfo->parent_id = 0;
                                        $serialNumberInfo->package_id = 0;
                                        $serialNumberInfo->package_storage_id = 0;
                                        $serialNumberInfo->storage_manage_id = $storageManageId;
                                        $serialNumberInfo->save();
                                    }
                                }

                                if ($sVal['serial_id'] != 0) {
                                    $productContentSerialId[] = $sVal['serial_no'];
                                    $snInfo = SerialNumberModel::where([
                                        'id' => $sVal['serial_id'],
                                        'status' => 1,
                                        'delete_flag' => 0
                                    ])->first();

                                    if (!empty($snInfo)) {

                                        $serialNumberList .= $snInfo['serial_no'] . ',';

                                    } else {
                                        $i = $sKey + 1;
                                        return ['code' => 1, 'msg' => '第' . $i . '个序列号状态不正确或不存在!', 'data' => ''];
                                    }

                                    if (!empty($smInfo)) {
                                        if ($smInfo['id'] == $sVal['storage_manage_id']) {//序列号所在库存与传来的仓库id查询的库存一致
                                            SerialNumberModel::where([
                                                'id' => $sVal['serial_id'],
                                                'status' => 1,
                                                'delete_flag' => 0
                                            ])->update([
                                                'package_id' => 0,
                                                'package_storage_id' => 0,
                                            ]);
                                        } else {//序列号库存与传来的仓库id查询的库存不一致,把原有的序列号库存id改成传来的
                                            SerialNumberModel::where([
                                                'id' => $sVal['serial_id'],
                                                'status' => 1,
                                                'delete_flag' => 0
                                            ])->update([
                                                'parent_id' => 0,
                                                'package_id' => 0,
                                                'package_storage_id' => 0,
                                                'storage_manage_id' => $smInfo['id'],
                                            ]);
                                        }
                                    } else {
                                        SerialNumberModel::where([
                                            'id' => $sVal['serial_id'],
                                            'status' => 1,
                                            'delete_flag' => 0
                                        ])->update([
                                            'parent_id' => 0,
                                            'package_id' => 0,
                                            'package_storage_id' => 0,
                                            'storage_manage_id' => $smId,
                                        ]);
                                    }
                                } else {
                                    $productContentSerialId[] = $sVal['serial_no'];
                                    $serialNumberList .= $sVal['serial_no'] . ',';

                                    SerialNumberModel::insert([
                                        'storage_manage_id' => $smId,
                                        'serial_no' => $sVal['serial_no'],
                                        'goods_id' => $val['type_id'],
                                        'main_id' => $data['main_id'],
                                        'created_at' => time(),
                                    ]);
                                }

                                $serialNum++;
                            }

                            if ($val['num'] > $serialNum) {
                                return ['code' => 1, 'msg' => '商品' . $productInfo['materiel_name'] . '返仓数量与选择的序列号数量不相等', 'data' => ''];
                            }

                        } else {
                            return ['code' => 1, 'msg' => '商品' . $productInfo['materiel_name'] . '开启了序列号，请选择序列号！', 'data' => ''];
                        }
                    } else {//未开启序列号的商品

                        if ($productInfo['num'] * $data['product_num'] != $val['num']) {
                            return ['code' => 1, 'msg' => '商品' . $productInfo['materiel_name'] . '返仓数量不正确，数量应是：' . $productInfo['num'] * $data['product_num'], 'data' => ''];
                        }
                    }

                    if (!empty($serialNumberList))
                        $serialNumberList = substr($serialNumberList, 0, strrpos($serialNumberList, ","));

                    $logData[] = [
                        'type' => 0,
                        'curr_storage_manage_id' => !empty($smInfo) ? $smInfo['id'] : $smId,
                        'storage_id' => $storageInfo['id'],
                        'storage_name' => $storageInfo['storage_name'],
                        'storage_address' => $storageInfo['storage_address'],
                        'materiel_class_id' => $productInfo['materiel_class_id'],
                        'materiel_class_name' => !empty($mcInfo['class_name']) ? $mcInfo['class_name'] : "",
                        'materiel_class_no' => !empty($mcInfo['class_no']) ? $mcInfo['class_no'] : "",
                        'materiel_type_id' => $val['type_id'],
                        'materiel_name' => $productInfo['materiel_name'],
                        'type_name' => $productInfo['type_name'],
                        'materiel_no' => $productInfo['materiel_no'],
                        /* 'purchase_no' => $productInfo['product_no'], */
                        'operate_num' => $productInfo['num'],
                        'last_storage_num' => !empty($smInfo) ? $smInfo['in_storage_num'] : 0,
                        'next_storage_num' => !empty($smInfo) ? $smInfo['in_storage_num'] + $val['num'] : $val['num'],
                        'materiel_mean_cost' => $productInfo['cost'],
                        'serial_number' => !empty($serialNumberList) ? $serialNumberList : "",
                        'all_id_type' => 6,
                        'all_id' => $data['product_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => strtotime($data['in_storage_time']),
                        'created_at' => time(),
                        'shelf_id' => !empty($storageInfo['shelf_id']) ? $storageInfo['shelf_id'] : '',
                        'remark' => empty($val['remark']) ? '' : $val['remark'],
                        'location_id' => !empty($storageInfo['location_id']) ? $storageInfo['location_id'] : '',
                    ];
                }
                if (!empty($logData)) {
                    LogInStorageModel::insert($logData);
                }

                StorageManageModel::where('id', $productStorageManageInfo['id'])->update([
                    'in_storage_num' => $productStorageManageInfo['in_storage_num'] - $data['product_num'],
                    'virtual_storage_num' => $productStorageManageInfo['virtual_storage_num'] - $data['product_num']
                ]);
                PackageComponentWarehouseLogModel::insertGetId([
                    'storage_manage_id' => $productStorageManageInfo['id'],
                    'product_id' => $productStorageManageInfo['type_id'],
                    'operation_num' => $data['product_num'],
                    'next_storage_num' => $productStorageManageInfo['in_storage_num'] - $data['product_num'],
                    'main_id' => $productStorageManageInfo['main_id'],
                    'operation_time' => strtotime($data['in_storage_time']),
                    'created_at' => time()
                ]);

                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
            } catch (Exception $e) {
                DB::rollBack();
                Log::debug('组件返仓异常' . var_export($e->getMessage(), true));
                return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
            }
        } else {
            return ['code' => 1, 'msg' => '组件里的商品，不能为空！', 'data' => ''];
        }
    }

    public static function handleReturnPackageStore1($data)
    {
        $smId = 0;
        $smCondition = [];
        $logData = [];
        //查询套餐库存信息
        $productStorageManageInfo = StorageManageModel::where([
            'id' => $data['storage_manage_id'],
            'type_id' => $data['product_id'],
            'is_product_materiel' => 1,
            'delete_flag' => 0
        ])->first();

        if (empty($productStorageManageInfo))
            return ['code' => 1, 'msg' => '没有找到，套餐' . $productStorageManageInfo['materiel_name'] . '库存信息！', 'data' => ''];

        if ($productStorageManageInfo['in_storage_num'] - $data['product_num'] < 0) {
            return ['code' => 1, 'msg' => '套餐' . $productStorageManageInfo['materiel_name'] . '库存数量不足！', 'data' => ''];
        }

        if ($productStorageManageInfo['virtual_storage_num'] - $data['product_num'] < 0) {
            return ['code' => 1, 'msg' => '套餐' . $productStorageManageInfo['materiel_name'] . '虚拟库存数量不足！', 'data' => ''];

        }
        $productContent = json_decode($data['product_content'], true);

        if (!empty($productContent)) {
            DB::beginTransaction();
            try {
                foreach ($productContent as $key => $val) {
                    //查询组件中的商品信息
                    $productInfo = MaterielProductContentModel::select('a.num', 'b.*')
                        ->from("materiel_product_content as a")
                        ->leftJoin('materiel_type as b', 'a.type_id', '=', 'b.id')
                        ->where('a.product_id', $data['product_id'])
                        ->where('b.id', $val['type_id'])
                        ->where('a.delete_flag', 0)
                        ->where('b.delete_flag', 0)
                        ->first();
                    if (empty($productInfo))
                        return ['code' => 1, 'msg' => '没有找到，商品' . $productInfo['materiel_name'] . '的信息', 'data' => ''];

                    /* DB::enableQueryLog(); */
                    //查询默认仓库和货架信息
                    if (empty($val['shelf_id']) || empty($val['location_id'])) {

                        $storageInfo = StorageModel::select('a.*', 'b.id as shelf_id', 'c.id as location_id')->from('storage as a')
                            ->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
                            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
                            ->where('a.id', $val['storage_id'])
                            ->where('a.delete_flag', 0)
                            ->where('b.status', 1)
                            ->where('c.location_type', 1)
                            ->where('b.shelf_type', 1)
                            ->first();

                    } else {
                        $storageInfo = StorageModel::select('a.*', 'b.id as shelf_id', 'c.id as location_id')->from('storage as a')
                            ->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
                            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
                            ->where('a.id', $val['storage_id'])
                            ->where('b.id', $val['shelf_id'])
                            ->where('c.id', $val['location_id'])
                            ->where('a.delete_flag', 0)
                            ->where('b.status', 1)
                            ->first();

                    }
                    /* echo "<pre>";
                       var_dump($storageInfo);die; */
                    if (empty($storageInfo))
                        return ['code' => 1, 'msg' => '没有找到，商品' . $productInfo['materiel_name'] . '选择的仓库信息', 'data' => ''];
                    $mcInfo = MaterielClassModel::select('id', 'class_name', 'class_no')
                        ->where(['delete_flag' => 0, 'id' => $productInfo['materiel_class_id']])->first();

                    //查询库存信息的条件
                    $smCondition = [
                        'type_id' => $val['type_id'],
                        'storage_id' => $val['storage_id'],
                        'delete_flag' => 0
                    ];
                    //DB::enableQueryLog();
                    //查询库存信息
                    $smInfo = StorageManageModel::where($smCondition)->first();
                    /*  echo "<pre>";
                echo var_dump(DB::getQueryLog());die; */
                    //判断商品仓库对应的库存是否存在，存在就修改在库数量和虚拟数量，不存在就新增库存信息
                    if (!empty($smInfo)) {//有商品库存信息
                        StorageManageModel::where('id', $smInfo['id'])->update([
                            'in_storage_num' => $smInfo['in_storage_num'] + $val['num'],
                            'virtual_storage_num' => $smInfo['virtual_storage_num'] + $val['num']
                        ]);

                    } else {//没有商品库存信息

                        $smId = StorageManageModel::insertGetId([
                            'materiel_class_id' => !empty($mcInfo['id']) ? $mcInfo['id'] : 0,
                            'materiel_class_name' => !empty($mcInfo['materiel_class_name']) ? $mcInfo['materiel_class_name'] : "",
                            'materiel_class_no' => !empty($mcInfo['materiel_class_no']) ? $mcInfo['materiel_class_no'] : "",
                            'type_id' => $val['type_id'],
                            'materiel_name' => !empty($productInfo['materiel_name']) ? $productInfo['materiel_name'] : "",
                            'type_name' => !empty($productInfo['type_name']) ? $productInfo['type_name'] : "",
                            'materiel_no' => !empty($productInfo['materiel_no']) ? $productInfo['materiel_no'] : "",
                            'materiel_mean_cost' => !empty($productInfo['cost']) ? $productInfo['cost'] : "",
                            'storage_id' => $storageInfo['id'],
                            'storage_name' => !empty($storageInfo['storage_name']) ? $storageInfo['storage_name'] : "",
                            'storage_address' => !empty($storageInfo['storage_address']) ? $storageInfo['storage_address'] : "",
                            'in_storage_num' => $val['num'],
                            'virtual_storage_num' => $val['num'],
                            'main_id' => $data['main_id'],
                            'in_storage_time' => strtotime($data['in_storage_time']),
                            'shelf_id' => !empty($storageInfo['shelf_id']) ? $storageInfo['shelf_id'] : 0,
                            'location_id' => !empty($storageInfo['location_id']) ? $storageInfo['location_id'] : 0,
                            'created_at' => time(),
                        ]);

                    }
                    $serialNumberList = "";
                    //开启序列号商品相关操作
                    if ($productInfo['is_use_serial'] == 1) {//开启序列号
                        if (!empty($val['serial_info'])) {
                            $serialNum = 0;
                            /* echo "<pre>";
                         var_dump($val['serial_info']);die; */
                            foreach ($val['serial_info'] as $sKey => $sVal) {
                                $snInfo = SerialNumberModel::where([
                                    'id' => $sVal['serial_id'],
                                    'status' => 1,
                                    'delete_flag' => 0
                                ])->first();
                                if (!empty($snInfo)) {
                                    $serialNumberList .= $snInfo['serial_no'] . ',';
                                } else {
                                    $i = $sKey + 1;
                                    return ['code' => 1, 'msg' => '第' . $i . '个序列号状态不正确或不存在!', 'data' => ''];
                                }

                                if (!empty($smInfo)) {
                                    if ($smInfo['id'] == $sVal['storage_manage_id']) {//序列号所在库存与传来的仓库id查询的库存一致
                                        SerialNumberModel::where([
                                            'id' => $sVal['serial_id'],
                                            'status' => 1,
                                            'delete_flag' => 0
                                        ])->update([
                                            'package_id' => 0,
                                            'package_storage_id' => 0,
                                        ]);
                                    } else {//序列号库存与传来的仓库id查询的库存不一致,把原有的序列号库存id改成传来的
                                        SerialNumberModel::where([
                                            'id' => $sVal['serial_id'],
                                            'status' => 1,
                                            'delete_flag' => 0
                                        ])->update([
                                            'package_id' => 0,
                                            'package_storage_id' => 0,
                                            'storage_manage_id' => $smInfo['id'],
                                        ]);
                                    }
                                } else {
                                    SerialNumberModel::where([
                                        'id' => $sVal['serial_id'],
                                        'status' => 1,
                                        'delete_flag' => 0
                                    ])->update([
                                        'package_id' => 0,
                                        'package_storage_id' => 0,
                                        'storage_manage_id' => $smId,
                                    ]);
                                }

                                $serialNum += $sVal['num'];
                            }

                            if ($val['num'] != $serialNum) {
                                return ['code' => 1, 'msg' => '商品' . $productInfo['materiel_name'] . '返仓数量与选择的序列号数量不相等', 'data' => ''];
                            }

                        } else {
                            return ['code' => 1, 'msg' => '商品' . $productInfo['materiel_name'] . '开启了序列号，请选择序列号！', 'data' => ''];
                        }
                    } else {//未开启序列号的商品

                        if ($productInfo['num'] * $data['product_num'] != $val['num']) {
                            return ['code' => 1, 'msg' => '商品' . $productInfo['materiel_name'] . '返仓数量不正确，数量应是：' . $productInfo['num'] * $data['product_num'], 'data' => ''];
                        }
                    }

                    if (!empty($serialNumberList))
                        $serialNumberList = substr($serialNumberList, 0, strrpos($serialNumberList, ","));

                    $logData[] = [
                        'type' => 0,
                        'curr_storage_manage_id' => !empty($smInfo) ? $smInfo['id'] : $smId,
                        'storage_id' => $storageInfo['id'],
                        'storage_name' => $storageInfo['storage_name'],
                        'storage_address' => $storageInfo['storage_address'],
                        'materiel_class_id' => $productInfo['materiel_class_id'],
                        'materiel_class_name' => !empty($mcInfo['class_name']) ? $mcInfo['class_name'] : "",
                        'materiel_class_no' => !empty($mcInfo['class_no']) ? $mcInfo['class_no'] : "",
                        'materiel_type_id' => $val['type_id'],
                        'materiel_name' => $productInfo['materiel_name'],
                        'type_name' => $productInfo['type_name'],
                        'materiel_no' => $productInfo['materiel_no'],
                        /* 'purchase_no' => $productInfo['product_no'], */
                        'operate_num' => $productInfo['num'],
                        'last_storage_num' => !empty($smInfo) ? $smInfo['in_storage_num'] : 0,
                        'next_storage_num' => !empty($smInfo) ? $smInfo['in_storage_num'] + $val['num'] : $val['num'],
                        'materiel_mean_cost' => $productInfo['cost'],
                        'serial_number' => !empty($serialNumberList) ? $serialNumberList : "",
                        'all_id_type' => 6,
                        'all_id' => $data['product_id'],
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => strtotime($data['in_storage_time']),
                        'created_at' => time(),
                        'shelf_id' => !empty($storageInfo['shelf_id']) ? $storageInfo['shelf_id'] : '',
                        'remark' => empty($val['remark']) ? '' : $val['remark'],
                        'location_id' => !empty($storageInfo['location_id']) ? $storageInfo['location_id'] : '',
                    ];
                }
                if (!empty($logData)) {
                    LogInStorageModel::insert($logData);
                }

                StorageManageModel::where('id', $productStorageManageInfo['id'])->update([
                    'in_storage_num' => $productStorageManageInfo['in_storage_num'] - $data['product_num'],
                    'virtual_storage_num' => $productStorageManageInfo['virtual_storage_num'] - $data['product_num']
                ]);
                PackageComponentWarehouseLogModel::insertGetId([
                    'storage_manage_id' => $productStorageManageInfo['id'],
                    'product_id' => $productStorageManageInfo['type_id'],
                    'operation_num' => $data['product_num'],
                    'next_storage_num' => $productStorageManageInfo['in_storage_num'] - $data['product_num'],
                    'main_id' => $productStorageManageInfo['main_id'],
                    'operation_time' => strtotime($data['in_storage_time']),
                    'created_at' => time()
                ]);

                DB::commit();
                return ['code' => 0, 'msg' => 'success', 'data' => ''];
            } catch (Exception $e) {
                DB::rollBack();
                Log::debug('组件返仓异常' . var_export($e->getMessage(), true));
                return ['code' => 1, 'msg' => '组件返仓失败！', 'data' => ''];
            }
        } else {
            return ['code' => 1, 'msg' => '组件里的商品，不能为空！', 'data' => ''];
        }
    }

    public static function serialList(array $data)
    {
        $materielTypeInfo = MaterielTypeModel::where([
            'id' => $data['type_id']
        ])
            ->first();

        if (!$materielTypeInfo['is_product_materiel']) {
            $data['pageSize'] = $data['pageSize'] ?? 20;
            $data['currentPage'] = $data['currentPage'] ?? 1;

            $query = SerialNumberModel::select(
                'a.id',
                'serial_no',
                'goods_id as materiel_type_id',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.in_storage_num',
                'd.id as storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.is_product_materiel',
                'a.storage_manage_id'
            )->from('serial_number as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.goods_id')
                ->leftJoin('storage_manage as c', 'c.id', '=', 'a.storage_manage_id')
                ->leftJoin('storage as d', 'd.id', '=', 'c.storage_id');
            if (!empty($data['keyword'])) {
                $query->where(function ($query) use ($data) {
                    $query->where('a.serial_no', 'like', '%' . $data['keyword'] . '%');
                });
            }
            $result = $query->where([
                'goods_id' => $data['type_id'],
                'storage_manage_id' => $data['id'],
                'status' => 1,
                'a.delete_flag' => 0,
                'package_storage_id' => 0
            ])
                ->paginate($data['pageSize'], ['*'], '', $data['currentPage']);
        } else {
            $query = SerialNumberModel::select(
                'a.id',
                'serial_no',
                'goods_id as materiel_type_id',
                'b.materiel_name',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'c.in_storage_num',
                'd.id as storage_id',
                'd.storage_name',
                'd.storage_address',
                'b.is_product_materiel',
                'a.storage_manage_id'
            )->from('serial_number as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.goods_id')
                ->leftJoin('storage_manage as c', 'c.id', '=', 'a.storage_manage_id')
                ->leftJoin('storage as d', 'd.id', '=', 'c.storage_id')
                ->with('serialInfo', function ($query) {
                    $query->select(
                        'serial_number.id',
                        'serial_no',
                        'package_storage_id as storage_manage_id',
                        'parent_id',
                        'a.materiel_name',
                        'a.type_name',
                        'a.materiel_no',
                        'a.materiel_img'
                    )
                        ->leftJoin('materiel_type as a', 'a.id', '=', 'serial_number.goods_id')
                        ->where('status', 1);
                });
            if (!empty($data['keyword'])) {
                $query->where(function ($query) use ($data) {
                    $query->where('a.serial_no', 'like', '%' . $data['keyword'] . '%');
                });
            }
            $result = $query->where([
                'goods_id' => $data['type_id'],
                'parent_id' => 0,
                'storage_manage_id' => $data['id'],
                'status' => 1,
                'a.delete_flag' => 0,
            ])
                ->paginate($data['pageSize'], ['*'], '', $data['currentPage']);
        }
        return $result;
    }

    private static function getWarehouseInfo($data)
    {
        //获取并检查仓库信息
        $storageInfo = StorageModel::query()->where([
            'id' => $data['storage_id'],
        ])->first();

        if (empty($storageInfo)) {
            throw new Exception('入库目标仓库不存在，请重试');
        }

        $shelfId = 0;
        $locationId = 0;

        //验证货架
        if (empty($data['location_id'])) {
            $shelfInfo = StorageShelfModel::where('storage_id', $data['storage_id'])->where('shelf_type', 1)->first();
            $locationInfo = StorageShelfLocationModel::where([
                'shelf_id' => $shelfInfo['id'],
                'location_type' => 1
            ])->first();

            $shelfId = $shelfInfo['id'];
            $locationId = $locationInfo['id'];
        } else {
            $shelfId = $data['shelf_id'];
            $locationId = $data['location_id'];
        }

        $result['storage_id'] = $data['storage_id'];
        $result['storage_name'] = $storageInfo['storage_name'];
        $result['storage_address'] = $storageInfo['storage_address'];
        $result['shelf_id'] = $shelfId;
        $result['location_id'] = $locationId;

        return $result;
    }

    //批量入库
    public static function directInStorageSeveral(array $data, int $time)
    {
        $goodsInfo = json_decode($data['goods_info'], true);
        DB::beginTransaction();
        try {
            $logData = [];
            $serialData = [];
            $storageManageInfo = [];
            $batchData = [];
            $logRes = "";
            $storageBatchModel = StorageBatchModel::query();
            foreach ($goodsInfo as $value) {
                $value['num'] = empty($value['num']) ? 0 : $value['num'];
                //获取入库目标商品信息
                $materielTypeInfo = MaterielTypeModel::query()->select(
                    'a.*',
                    'b.class_name as sec_class_name',
                    'b.class_no as sec_class_no'
                )
                    ->from('materiel_type as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->where('a.id', $value['type_id'])->first();

                if ($materielTypeInfo['delete_flag']) {
                    throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '不存在或已被删除，请重试');
                }
                if (empty($value['storage_id'])) {
                    throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '需选择入库仓库');
                }
                if (empty($value['location_id']) || empty($value['shelf_id'])) {
                    if (!empty($data['is_share_shelf_location'])) {
                        throw new Exception('您开启强制选择货架及库位，请选择！');
                    }
                }
                if (!empty($value['shelf_id']) && empty($value['location_id'])) {
                    $locationInfo = StorageShelfLocationModel::query()->where([
                        'storage_id' => $value['storage_id'],
                        'shelf_id' => $value['shelf_id'],
                        'status' => 1,
                        'location_type' => 1
                    ])->first();
                    if (!empty($locationInfo)) $value['location_id'] = $locationInfo->id;
                    if (!StorageShelfLocationModel::query()->where([
                        'storage_id' => $value['storage_id'],
                        'shelf_id' => $value['shelf_id'],
                        'status' => 1,
                    ])->exists()) {
                        throw new Exception('您选择货架暂无库位，请创建库位！');
                    }
                }
                $storageInfo = self::getWarehouseInfo([
                    'storage_id' => $value['storage_id'],
                    'location_id' => empty($value['location_id']) ? 0 : $value['location_id'],
                    'shelf_id' => empty($value['shelf_id']) ? 0 : $value['shelf_id'],
                    'is_use_shelf' => $data['is_use_shelf'],
                ]);
                $storageId = $storageInfo['storage_id'];
                $storageName = $storageInfo['storage_name'];
                $storageAddress = $storageInfo['storage_address'];
                $locationId = $storageInfo['location_id'];
                $shelfId = $storageInfo['shelf_id'];

                $logRes .= '商品名称：' . $materielTypeInfo['materiel_name'] .
                    '入库数量：' . $value['num'] . '仓库名：' . $storageName . '、';
                //是否套餐当组件使用
                if ($materielTypeInfo['is_product_materiel'] && $data['is_use_packages_components']) {
                    $requestPackageInfo = [];
                    $requestPackageInfo ['id'] = $materielTypeInfo['id'];
                    $requestPackageInfo ['materiel_name'] = $materielTypeInfo['materiel_name'];
                    $requestPackageInfo ['shelf_id'] = $value['shelf_id'];
                    $requestPackageInfo ['location_id'] = $value['location_id'];
                    $requestPackageInfo ['storage_id'] = $value['storage_id'];
                    $requestPackageInfo ['num'] = $value['num'];
                    $requestPackageInfo ['supplier_id'] = $value['binding_supplier'] ?? 0;
                    $requestPackageInfo ['is_use_serial'] = $materielTypeInfo['is_use_serial'];
                    $data['operation_type'] = 2;
                    $data['all_id_type'] = 0;
                    $requestPackageInfo ['sell_price'] = $materielTypeInfo['selling_price'];
                    StorageManageService::packageComponentHandle($requestPackageInfo, $data);
                } else {
                    //检查商品是否已存在库存
                    $checkStorageManageInfo = StorageManageModel::where([
                        'type_id' => $materielTypeInfo['id'],
                        'location_id' => $locationId,
                        'storage_id' => $value['storage_id'],
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0
                    ])->first();
                    /*$manageInfo = StorageManageModel::query()
                        ->where([
                            'location_id' => $locationId,
                            'storage_id' => $value['storage_id'],
                            'main_id' => $data['main_id'],
                            'delete_flag' => 0,
                            ['in_storage_num', '>', 0]
                        ])->first();
                    if (empty($manageInfo)) {
                        StorageShelfLocationModel::query()
                            ->where([
                                'status' => 1,
                                'id' => $locationId,
                                'shelf_id' => $value['shelf_id'],
                            ])->update(['log_no' => getNO('storage_shelf_location', 'log_no')]);
                    }*/
                    $productUseTag = $materielTypeInfo['is_product_materiel'] ? 1 : 0;
                    MaterielTypeModel::where('id', $materielTypeInfo['id'])
                        ->update([
                            'product_use_tag' => $productUseTag
                        ]);

                    $storageManageId = 0;//库存id
                    $lastStorageNum = 0;//操作前数量
                    $nextStorageNum = 0;//操作后数量
                    //查询商品所有存在信息
                    $inventoryInfo = StorageManageModel::query()->where([
                        'type_id' => $materielTypeInfo['id'],
                        'main_id' => $data['main_id'],
                        'delete_flag' => 0
                    ])->select(
                        'id',
                        'materiel_mean_cost',
                        DB::raw('SUM(in_storage_num) as total_in_num')
                    )->first();
                    $meanPirce = $value['cost'] ?? 0;
                    if (!empty($inventoryInfo) && !empty($inventoryInfo['id'])) {
                        $totalMoney = 0;
                        if (!empty($inventoryInfo['materiel_mean_cost']) && !empty($inventoryInfo['total_in_num'])) {
                            $totalMoney = $inventoryInfo['materiel_mean_cost'] * $inventoryInfo['total_in_num'];
                        }
                        $totalCost = 0;
                        if (!empty($value['num']) && !empty($value['cost'])) {
                            $totalCost = $value['num'] * $value['cost'];
                        }
                        $totalNum = $inventoryInfo['total_in_num'] + $value['num'];
                        $money = $totalMoney + $totalCost;
                        if (!empty($totalNum) && !empty($money)) {
                            $meanPirce = sprintf("%.6f", ($money)
                                /
                                ($totalNum));
                        }
                    }
                    if (empty($checkStorageManageInfo)) {
                        //                    $sortFlag = 0;//是否达到预警数0:否;1:是;
                        $alertNum = empty($value['alert_num']) ? 0 : $value['alert_num'];
                        //                    if($alertNum > 0 && ($alertNum > $value['num'])) {
                        //                        $sortFlag = 1;
                        //                    }
                        $storageManageId = StorageManageModel::insertGetId([
                            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                            'materiel_class_name' => $materielTypeInfo['sec_class_name'],
                            'materiel_class_no' => $materielTypeInfo['sec_class_no'],
                            'type_id' => $materielTypeInfo['id'],
                            'materiel_name' => $materielTypeInfo['materiel_name'],
                            'type_name' => $materielTypeInfo['type_name'],
                            'materiel_no' => $materielTypeInfo['materiel_no'],
                            'materiel_mean_cost' => $meanPirce ?? 0,
                            'storage_id' => $storageId,
                            'storage_name' => $storageName,
                            'storage_address' => $storageAddress,
                            'in_storage_num' => $value['num'],
                            'alert_num' => $alertNum,
                            'virtual_storage_num' => 0,
                            'main_id' => $data['main_id'],
                            'in_storage_time' => $data['in_storage_time'],
                            'is_product_materiel' => $materielTypeInfo['is_product_materiel'],
                            'created_at' => $time,
                            'shelf_id' => $shelfId,
                            'location_id' => $locationId,
                            //                        'sort_flag' => $sortFlag
                        ]);

                        $nextStorageNum = $value['num'];
                    } else {
                        $storageManageId = $checkStorageManageInfo['id'];
                        $lastStorageNum = $checkStorageManageInfo['in_storage_num'];
                        $nextStorageNum = $checkStorageManageInfo['in_storage_num'] + $value['num'];

                        //                    $sortFlag = 0;//是否达到预警数0:否;1:是;
                        $alertNum = empty($value['alert_num']) ? $checkStorageManageInfo['alert_num'] : $value['alert_num'];
                        //                    if($alertNum > 0 && ($alertNum > $nextStorageNum)) {
                        //                        $sortFlag = 1;
                        //                    }

                        $storageManageInfo[] = [
                            'id' => $checkStorageManageInfo['id'],
                            'in_storage_num' => $nextStorageNum,
                            //'virtual_storage_num' => $checkStorageManageInfo['virtual_storage_num'] + $value['num'],
                            'alert_num' => $alertNum,
                            //                        'sort_flag' => $sortFlag,
                            'materiel_mean_cost' => $meanPirce ?? 0,
                        ];
                    }

                    $serialNoStr = '';
                    if ($materielTypeInfo['is_use_serial']) {
                        if (empty($value['serial_no'])) {
                            throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '已开启使用序列号，请添加序列号后重试');
                        }

                        $serialNoArr = array_filter(explode(',', $value['serial_no']), function ($v) {
                            return $v !== '';
                        });

                        if (count($serialNoArr) < $value['num']) {
                            throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '所需序列号数量X' . $value['num'] . ',尚缺序列号数量X' . ($value['num'] - count($serialNoArr)));
                        }

                        if (count($serialNoArr) > $value['num']) {
                            throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '所需序列号数量X' . $value['num'] . ',超出所需数量X' . (count($serialNoArr) - $value['num']));
                        }

                        foreach ($serialNoArr as $serialArrValue) {
                            //验证序列号
                            $serialInfo = SerialNumberModel::getSerialInfoByTypeId($value['type_id'], $serialArrValue, $data['main_id']);

                            if (!empty($serialInfo)) {
                                throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '的序列号:' . $serialArrValue . '已存在，无法重复录入');
                            }

                            $serialData[] = [
                                'storage_manage_id' => $storageManageId,
                                'package_storage_id' => $materielTypeInfo['is_product_materiel'] ? $storageManageId : 0,
                                'package_id' => $materielTypeInfo['is_product_materiel'] ? $materielTypeInfo['id'] : 0,
                                'serial_no' => $serialArrValue,
                                'goods_id' => $value['type_id'],
                                'main_id' => $data['main_id'],
                                'status' => 1,
                                'created_at' => $time,
                                'batch_no' => $value['batch_no'] ?? ''
                            ];
                        }
                        $serialNoStr = $value['serial_no'];
                    }

                    $logData = [
                        'type' => 2,
                        'batch_no' => $value['batch_no'] ?? '',
                        'curr_storage_manage_id' => $storageManageId,
                        'storage_id' => $storageId,
                        'storage_name' => $storageName,
                        'storage_address' => $storageAddress,
                        'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                        'materiel_class_name' => $materielTypeInfo['sec_class_name'],
                        'materiel_class_no' => $materielTypeInfo['sec_class_no'],
                        'materiel_type_id' => $materielTypeInfo['id'],
                        'materiel_name' => $materielTypeInfo['materiel_name'],
                        'type_name' => $materielTypeInfo['type_name'],
                        'materiel_no' => $materielTypeInfo['materiel_no'],
                        'purchase_no' => '',
                        'operate_num' => $value['num'],
                        'last_storage_num' => $lastStorageNum,
                        'next_storage_num' => $nextStorageNum,
                        'materiel_mean_cost' => $value['cost'],
                        'serial_number' => $serialNoStr,
                        'all_id_type' => 0,
                        'all_id' => 0,
                        'user_id' => $data['user_id'],
                        'main_id' => $data['main_id'],
                        'in_storage_time' => $data['in_storage_time'],
                        'created_at' => $time,
                        'shelf_id' => $shelfId,
                        'remark' => empty($value['remark']) ? '' : $value['remark'],
                        'label_id' => $data['label_id'],
                        'label_name' => $data['label_name'],
                        'general_remarks' => !empty($data['general_remarks']) ? $data['general_remarks'] : '',
                        'location_id' => $locationId,
                        'supplier_id' => !empty($value['binding_supplier']) ? $value['binding_supplier'] : 0,
                    ];
                    $inLogId = LogInStorageModel::query()->insertGetId($logData);
                    MessageService::sendInSms(
                        '',
                        $materielTypeInfo['materiel_name'],
                        $materielTypeInfo['type_name'],
                        $storageId,
                        $storageName,
                        $data,
                        $value['num'],
                        $nextStorageNum,
                        $inLogId
                    );

                    if (!empty($value['batch_no'])) {
                        if ($storageBatchModel->where('batch_no', $value['batch_no'])->exists()) {
                            throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '批次号：' . $value['batch_no'] . '，已存在,请重新填写！');
                        };
                        if (isset($value['expiration_date'])) {
                            if ($value['expiration_date'] <= 0) {
                                $value['expiration_date'] = "";
                            }
                        }
                        if (isset($value['warning_time'])) {
                            if ($value['warning_time'] <= 0) {
                                $value['warning_time'] = "";
                            }
                        }
                        if (!empty($value['expiration_date']) && !empty($value['warning_time'])) {
                            if ($value['expiration_date'] < $value['warning_time']) {
                                throw new Exception('预警时间不能大于保质期');
                            }
                        }
                        $batchData[] = [
                            'batch_no' => $value['batch_no'],
                            'storage_manage_id' => $storageManageId,
                            'batch_num' => $value['num'],
                            'batch_left_num' => $value['num'],
                            'batch_cost' => $value['cost'] ?? 0,
                            'production_time' => !empty($value['production_time']) ? strtotime($value['production_time']) : '',
                            'delivery_time' => !empty($value['delivery_time']) ? strtotime($value['delivery_time']) : '',
                            'inspector' => !empty($value['inspector']) ? $value['inspector'] : '',
                            'binding_supplier' => !empty($value['binding_supplier']) ? $value['binding_supplier'] : '',
                            'expiration_date' => !empty($value['expiration_date']) ? $value['expiration_date'] : '',
                            'warning_time' => !empty($value['warning_time']) ? $value['warning_time'] : '',
                            'production_order_number' => !empty($value['production_order_number']) ? $value['production_order_number'] : '',
                            'external_order_number' => !empty($value['external_order_number']) ? $value['external_order_number'] : '',
                            'upload_credentials_img' => $value['upload_credentials_img'] ?? '',
                            'materiel_id' => 0,
                            'main_id' => $data['main_id'],
                            'created_at' => $time
                        ];

                    } else {
                        throw new Exception('商品:' . $materielTypeInfo['materiel_name'] . '，批次号不能为空');
                    }
                    StorageManageModel::where('type_id', $materielTypeInfo['id'])->update([
                        'materiel_mean_cost' => $meanPirce,
                    ]);
                    MaterielTypeModel::query()->where('id', $materielTypeInfo['id'])
                        ->update([
                            'cost' => $meanPirce,
                            'last_cost' => $materielTypeInfo['cost'],
                        ]);
                }
            }

            /*if (!empty($logData)) {
                LogInStorageModel::insert($logData);
            }*/

            if (!empty($serialData)) {
                SerialNumberModel::insert($serialData);
            }

            if (!empty($storageManageInfo)) {
                batch()->update(new StorageManageModel, $storageManageInfo, 'id');
            }
            if (!empty($batchData)) {
                $storageBatchModel->insert($batchData);
            }
            CommonService::cancelAlertFlag($data['main_id']);
            CommonService::operateResult($data['user_id'], $time, $data, $logRes);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('批量入库异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //批量删除库存信息
    static public function batchDel($data)
    {
        $data['model_type'] = $data['model_type'] ?? 1;
        $idArr = explode(',', $data['ids']);
        $list = StorageManageModel::query()
            ->where(['main_id' => $data['main_id'], 'delete_flag' => 0])
            ->where(function ($query) use ($data, $idArr) {
                if ($data['model_type'] == 1) {
                    $query->whereIn('storage_id', $idArr);
                } else {
                    $query->whereIn('id', $idArr);
                }
            })->get();
        $logData = '';
        if (!empty($list->toArray())) {
            foreach ($list as $val) {
                /*  if($val['in_storage_num'] > 0) {
                    return [
                        'code' => 1,
                        'msg' => '库存数为0时才可删除，当前'.$val['materiel_name'].'库存数为：'.$val['in_storage_num'],
                        'data' => ''
                    ];
                } */
                $val->delete_flag = 1;
                $val->save();
                $logData .= '商品名称：' . $val['materiel_name'] . ' 仓库:' . $val['storage_name'] . ' 库存已删除，';
            }
        }
        CommonService::log('批量删除库存信息', $data, $logData);
        return ['code' => 0, 'msg' => '删除成功', 'data' => ''];
    }

    /**
     * 修改预警数
     * @param unknown $data
     * @return unknown
     */
    static public function updAlertNum($data)
    {
        return StorageManageModel::where([
            'main_id' => $data['main_id'],
            'delete_flag' => 0
        ])->where('id', $data['id'])->update(['alert_num' => $data['alert_num']]);
    }

    /**
     * 删除序列号（适用于批量）
     * @param unknown $data
     * @return \Illuminate\Http\JsonResponse
     */
    static public function delSerialNo($data)
    {
        $idArr = explode(',', $data['ids']);

        DB::beginTransaction();
        try {
            $serialList = SerialNumberModel::where([
                'main_id' => $data['main_id'],
                'status' => 1,
                'parent_id' => 0,
                'delete_flag' => 0
            ])->whereIn('id', $idArr)->get()->toArray();

            if (empty($serialList)) {
                throw new \Exception('序列号信息不存在');
            }
            foreach ($serialList as $val) {
                $query = StorageManageModel::where('type_id', $val['goods_id']);
                if (!empty($val['storage_manage_id']))
                    $query->where('id', $val['storage_manage_id']);
                $query->where('in_storage_num', '>', 0)->decrement('in_storage_num');
                SerialNumberModel::where([
                    'id' => $val['id']
                ])->update(['delete_flag' => 1]);
                $val['serial_id'] = $val['id'];
                $val['delete_flag'] = 1;
                $val['created_at'] = Carbon::now()->timestamp;
                unset($val['id']);
                DelSerialNumberModel::insert($val);
                $serialNo .= $val['serial_no'] . '、';
            }
            $logData = '序列号：' . $serialNo . '已删除！';
            CommonService::log('删除序列号', $data, $serialNo);
            DB::commit();
            return success();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('删除序列号异常:' . var_export($e->getMessage(), true));
            return fail('', $e->getMessage());
        }

    }

    /**
     * 修改批次号
     * @param $data
     */
    static public function updBatchNo($data)
    {
        $param = 'upload_credentials_img';
        $batchInfo = StorageBatchModel::select('id', 'batch_no', $param)
            ->where([
                'id' => $data['id'],
                'delete_flag' => 0,
                'main_id' => $data['main_id']
            ])->first()->toArray();
        $bool = false;
        $diffArray = [];
        if (!empty($batchInfo)) {
            if (!empty($data[$param]) && !empty($batchInfo[$param])) {
                $reqdata = explode(',', $data[$param]);
                $sqlData = explode(',', $batchInfo[$param]);
                $collection = collect($sqlData);
                $diffArray = $collection->diff($reqdata);
                $diffArray->all();
            }
            unset($data['id']);
            $bool = StorageBatchModel::where([
                'id' => $batchInfo['id'],
            ])->update($data);
        }
        if ($bool) {
            $logData = '批次号：' . $batchInfo['batch_no'] . '信息已修改';
            return ['code' => 0, 'reg' => $logData, 'data' => $diffArray];
        } else {
            return ['code' => 1];
        }
    }

    static public function sellOutStorage($requetData, $data, $sellId = 0, $isUseShelf = 0)
    {

        if (empty($data['content'])) {
            return ['code' => 1, 'msg' => '无可出库商品信息', 'data' => ''];
        }
        $batchArr = [];
        $outLogData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据
        $sellGoodsList = [];
        $storageBatchModel = StorageBatchModel::query();
        $sellInfo = SellModel::where('id', $data['all_id'])->first();
        foreach ($data['content'] as $key => $value) {
            $shelfId = empty($value['shelf_id']) ? 0 : $value['shelf_id'];
            $locationId = empty($value['location_id']) ? 0 : $value['location_id'];
            //物料商品信息
            $materielTypeInfo = MaterielsTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'a.id' => $value['type_id'],
                    'a.main_id' => $requetData['main_id'],
                    'a.delete_flag' => 0,
                ])->first();
            if (empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '物料`' . $value['name'] . '-' . $value['type_name'] . '`不存在', 'data' => ''];
            }
            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $requetData['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`' . $value['warehouse'] . '`不存在', 'data' => ''];
            }
            //物料当前库存信息
            if ($isUseShelf) {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'main_id' => $requetData['main_id'],
                    'delete_flag' => 0,
                    'shelf_id' => $shelfId,
                    'location_id' => $locationId,
                ])->first();
            } else {
                $storageManageInfo = StorageManageModel::where([
                    'type_id' => $materielTypeInfo['id'],
                    'storage_id' => $storageInfo['id'],
                    'main_id' => $requetData['main_id'],
                    'delete_flag' => 0,
                ])->first();
            }

            //检查库存中是否存在该物料
            if (empty($storageManageInfo)) {
                return ['code' => 1, 'msg' => '库存中物料`' . $value['name'] . '-' . $value['type_name'] . '`不存在', 'data' => ''];
            }
            if (!OperMainAccountModel::query()
                ->where([
                    'main_id' => $requetData['main_id'],
                    'delete_flag' => 0
                ])->exists()) {
                if ($storageManageInfo['in_storage_num'] < $value['num']) {
                    return ['code' => 1, 'msg' => $value['name'] . '-' . $value['type_name'] . '当前库存剩余数量' . $storageManageInfo['in_storage_num'] . '不足，无法完成出库', 'data' => ''];
                }
            }

            /* if ($storageManageInfo['virtual_storage_num'] < $value['num']) {
                 return ['code' => 1, 'msg' => $value['name'] . '-' . $value['type_name'] . '当前可用库存剩余数量(x' . $storageManageInfo['virtual_storage_num'] . ')不足，无法完成出库', 'data' => ''];
             }*/
            //扣除批次号
            $batchArr = Self::batchNoHandle($storageManageInfo, $value['batch_list'], $value['num'], $requetData);
            $outLogData['client_id'] = $sellInfo['customer_id'];//物料id
            $outLogData['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $outLogData['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $outLogData['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $outLogData['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $outLogData['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $outLogData['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $outLogData['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $outLogData['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $outLogData['type'] = 0;//type;0:出库;1:调出;
            $outLogData['storage_id'] = $storageInfo['id'];//仓库主键id
            $outLogData['storage_name'] = $storageInfo['storage_name'];//仓库名
            $outLogData['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $outLogData['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $outLogData['operate_num'] = $value['num'];//操作数量
            $outLogData['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $outLogData['sell_price'] = $value['price'];//物料均价
            $outLogData['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $outLogData['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $outLogData['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $outLogData['all_id'] = $data['all_id'];//单据id
            $outLogData['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $outLogData['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $outLogData['remark'] = empty($data['remark']) ? '' : $data['remark'];//备注
            $outLogData['user_id'] = $requetData['user_id'];//操作人用户id
            $outLogData['main_id'] = $requetData['main_id'];//主账号id
            $outLogData['shelf_id'] = $shelfId;
            $outLogData['location_id'] = $locationId;
            $outLogData['created_at'] = time();
            $outLogData['serial_number'] = $value['serial_no'];
            $outLogData['batch_no'] = $batchArr;
            $outLogData['shelf_id'] = $shelfId;
            $outLogData['location_id'] = $locationId;
            $sellGoodsList[] = [
                'materiel_type_id' => $materielTypeInfo['id'],
                'cost_price' => $storageManageInfo['materiel_mean_cost'],
                'num' => $value['num'],
                'main_id' => $requetData['main_id'],
                'sell_id' => $data['all_id'],
                'sell_date' => strtotime($sellInfo['sell_date']),
                'created_at' => time(),
            ];
            $logId = LogOutstorageModel::query()->insertGetId($outLogData);
            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'type_id' => $materielTypeInfo['id'],//物料id
                'num' => $value['num'],//出库数量
                'shelf_id' => empty($value['shelf_id']) ? '' : $value['shelf_id'],
                'location_id' => empty($value['location_id']) ? '' : $value['location_id'],
                'log_id' => $logId,
            ];
            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }
        try {
            //生成入库操作记录
            //LogOutstorageModel::insert($outLogData);
            //更新库存总数
            foreach ($outstorageNumsData as $val) {
                StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);
                StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
                //验证是否有预出库，有则跳过此步骤
                /*if($sellId != 0) {
                    $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                        ->where('materiel_type_id', $val['type_id'])
                        ->where(['shelf_id' => $shelfId,'location_id' => $locationId])->first();
                    if(empty($prepareInfo)) {
                        StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
                    }
                    StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);

                }*/
                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['alert_num'],
                    $datas = [
                        'user_id' => $requetData['user_id'],
                        'main_id' => $requetData['main_id']
                    ],
                    $storageInfo['id'],
                    $val['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $datas = [
                        'user_id' => $requetData['user_id'],
                        'main_id' => $requetData['main_id']
                    ],
                    $val['storage_name'],
                    $storageInfo['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['storage_name'],
                    $val['num'],
                    $datas = [
                        'user_id' => $requetData['user_id'],
                        'main_id' => $requetData['main_id']
                    ],
                    $storageInfo['id'],
                    $val['alert_num'],
                    $val['log_id']
                );
            }

            SellGoodsListModel::insert($sellGoodsList);
            return ['code' => 0, 'msg' => 'success', 'data' => $returnData];
        } catch (Exception $e) {
            Log::debug('出库：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }

    }

    //处理批次号对应的剩余出库数量
    private static function batchNumHandle($batchInfo, $outNum, $batchTitle, $sort)
    {
        $info = StorageBatchModel::query()->select(
            'id',
            'batch_left_num',
            'batch_no'
        )->where([
            'delete_flag' => 0,
            'storage_manage_id' => $batchInfo['storage_manage_id'],
            ['batch_left_num', '>', 0],
        ])->orderBy('created_at', $sort)->get();

        $surplusNum = 0;
        $batchArr = [];
        if (!empty($info)) {
            $batchList = $info->toArray();
            $batchTotalNum = array_sum(array_column($batchList, 'batch_left_num'));
            if ($batchTotalNum >= $outNum) {//出库数量小于批次号总剩余数量12
                foreach ($info as $val) {
                    $batchArr[] = $val['batch_no'];
                    $num = $outNum;
                    $outNum -= $val->batch_left_num;
                    if ($outNum < 0) {
                        $val->decrement('batch_left_num', $num);
                        break;
                    } else {
                        $val->batch_left_num = 0;
                        $val->save();
                        if ($outNum == 0) break;
                    }
                }
            } else {//出库数量大于批次号总剩余数量
                StorageBatchModel::query()->where([
                    'delete_flag' => 0,
                    'storage_manage_id' => $batchInfo['storage_manage_id'],
                    ['batch_left_num', '>', 0],
                ])->update(['batch_left_num' => 0]);
                $surplusNum = $outNum - $batchTotalNum;
                $batchArr = array_column($batchList, 'batch_no');

            }
        } else {
            $surplusNum = $outNum;
        }
        if (!empty($surplusNum)) {
            $batchNO = self::createBatchNo($batchInfo, $surplusNum, $batchTitle);
            if (!empty($batchNO)) $batchArr[count($batchArr)] = $batchNO;
        }
        return $batchArr;
    }

    //根据出库数量大于总批次号剩余数量，创建新的批次号
    public static function createBatchNo($batchInfo, $surplusNum, $batchTitle, $method = 'out')
    {
        $batchNo = '';
        $time = time();
        $storageBatchModel = StorageBatchModel::query();
        if (!empty($surplusNum)) {
            $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            do {
                $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            } while (!empty($storageBatchModel->where('batch_no', $batchNo)->first()));
            $batchData = [
                'batch_no' => $batchNo,
                'storage_manage_id' => $batchInfo['storage_manage_id'],
                'batch_num' => $surplusNum,
                'batch_left_num' => 0,
                'batch_cost' => $batchInfo['batch_cost'] ?? 0,
                'main_id' => $batchInfo['main_id'],
                'delivery_time' => $time,
                'production_time' => $time,
                'created_at' => $time
            ];
            if ($method == 'in') {
                $batchData ['batch_left_num'] = $surplusNum;
            }
            $storageBatchModel->insert($batchData);
        }
        return $batchNo;
    }

    /**
     *处理批次号公共方法
     * Author: zlf
     * Created at 2024/1/16 15:26
     * @param $storageManageInfo
     * @param $batchId
     * @param $num
     * @param $data
     * @return array|string
     */
    public static function batchNoHandle($storageManageInfo, $chooseBatchList, $num, $data)
    {
        $batchArr = [];
        $batchInfo = StorageBatchModel::query()->select(
            'id',
            'main_id',
            'batch_cost',
            'batch_left_num',
            'delete_flag',
            'storage_manage_id',
            'batch_no',
        );
        if (empty($chooseBatchList)) {//没有选择批次号，使用老的批次号
            $batchInfo->where([
                'delete_flag' => 0,
                'storage_manage_id' => $storageManageInfo['id'],
                ['batch_left_num', '>', 0],
            ]);
        } else {//选择了批次号
            if (is_array($chooseBatchList)) {
                $totalBatchNum = 0;
                foreach ($chooseBatchList as $cVal) {
                    if (!empty($cVal['batch_id'])) {
                        StorageBatchModel::query()
                            ->where(['id' => $cVal['batch_id']])
                            ->decrement('batch_left_num', $cVal['batch_num']);
                    }
                    $totalBatchNum += $cVal['batch_num'];
                    $batchArr[] = $cVal['batch_no'];
                }
                if (($num - $totalBatchNum) > 0) {
                    $surplusBatchNum = $num - $totalBatchNum;
                    $batchInfo = [
                        'batch_cost' => $storageManageInfo['materiel_mean_cost'],
                        'main_id' => $data['main_id'],
                        'storage_manage_id' => $storageManageInfo['id']
                    ];
                    $batchArr[] = self::createBatchNo($batchInfo, $surplusBatchNum, $data['batch_title']);
                }
                if (!empty($batchArr) && is_array($batchArr)) {
                    $batchArr = implode(',', $batchArr);
                }
                return $batchArr;
            } else {
                throw new \Exception('选择的批次号,数据异常');
            }
        }
        $isUseNewBatchNo = AdminAddendumModel::query()
            ->where(['main_id' => $data['main_id']])
            ->value('is_use_newest_batch_no');
        $sort = !empty($isUseNewBatchNo) ? 'desc' : 'asc';//是否使用最新的批次号
        $batchInfo = $batchInfo->orderBy('created_at', $sort)->get();
        if (!empty($batchInfo->toArray())) {
            $outNum = 0;
            foreach ($batchInfo as $bVal) {
                if ($bVal['batch_left_num'] >= $num) {//批次号剩余数量，正好够扣除出库数量。
                    $bVal['batch_left_num'] = $bVal['batch_left_num'] - $num;
                    $bVal->save();
                    $outNum = 0;
                    break;
                } else {//批次号剩余数量，不够扣除出库数量
                    $num -= $bVal['batch_left_num'];
                    $outNum += $num - $bVal['batch_left_num'];
                    $bVal['batch_left_num'] = 0;
                    $bVal->save();
                    if ($num <= 0) {
                        break;
                    }
                }
            }
            if (!empty($outNum)) {
                $batchArr = self::batchNumHandle($batchInfo[0], $outNum, $data['batch_title'], $sort);//处理批次号对应的剩余出库数量
            }
        } else {//批次号没有剩余数量，直接创建新的批次号
            $batchInfo = [
                'batch_cost' => $storageManageInfo['materiel_mean_cost'],
                'main_id' => $data['main_id'],
                'storage_manage_id' => $storageManageInfo['id']
            ];
            $batchArr = self::createBatchNo($batchInfo, $num, $data['batch_title']);
        }
        if (!empty($batchArr)) {
            if (is_array($batchArr) && !empty($batchInfo)) {
                $batchArr = array_merge($batchArr, array_column($batchInfo->toArray(), 'batch_no'));
            }
        } elseif (empty($batchArr) && !empty($batchInfo)) {
            $batchArr = array_column($batchInfo->toArray(), 'batch_no');

        }
        if (!empty($batchArr) && is_array($batchArr)) {
            $batchArr = implode(',', $batchArr);
        }
        return $batchArr;
    }

    static public function ChooseBatchList($data)
    {
        return StorageBatchModel::query()->select(
            'storage_batch.id',
            'batch_no',
            'storage_manage_id',
            'batch_num',
            'batch_left_num',
            'batch_cost',
        )->leftJoin('storage_manage as b',
            'b.id',
            '=',
            'storage_batch.storage_manage_id'
        )->where([
            'b.id' => $data['id'],
            'storage_batch.main_id' => $data['main_id'],
            ['batch_left_num', '>', 0],
            'storage_batch.delete_flag' => 0,
            'b.delete_flag' => 0
        ])->orderBy('storage_batch.created_at', $data['sort'])->get();
    }

    /**
     *处理套餐和组件同步使用
     * Author: zlf
     * Created at 2024/2/8 10:01
     * @param $packageInfo
     * @param $requestPackageInfo
     * @param $method //in 入库 out 出库
     * @return void
     */
    public static function packageComponentHandle($packageInfo, $data, $method = 'in')
    {
        if (!empty($packageInfo['is_use_serial'])) {
            throw  new \Exception('套餐:' . $packageInfo['materiel_name'] . '已开启序列号， 组件不能同步使用！');
        }
        $packageStorageNum = StorageManageModel::query()->where([
            'storage_id' => $packageInfo['storage_id'],
            'type_id' => $packageInfo['id'],
            'delete_flag' => 0,
            ['in_storage_num', '>', 0]
        ])->sum('in_storage_num');

        if (!empty($packageStorageNum)) {
            throw  new \Exception('套餐:' . $packageInfo['materiel_name'] . '的库存数量不为0， 组件不能同步使用！');
        }

        $storageInfo = StorageModel::query()->select(
            'id',
            'storage_name',
            'storage_address'
        )->where([
            'id' => $packageInfo['storage_id'],
            'delete_flag' => 0
        ])->first();
        if (empty($storageInfo)) {
            throw  new \Exception('套餐-' . $packageInfo['materiel_name'] . '，仓库不存在！');
        }
        if ($method === 'out')
            $data['in_storage_time'] = $data['out_storage_time'];
        $productContent = MaterielProductContentModel::query()
            ->select(
                'b.id',
                'cost',
                'a.num',
                'b.is_product_materiel',
                'materiel_name',
                'type_name',
                'materiel_no',
                'type_name',
                'materiel_class_id',
                'c.class_name as sec_class_name',
                'c.class_no as sec_class_no',
                'b.selling_price',
                'type_id'
            )->from('materiel_product_content as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
            ->where([
                'product_id' => $packageInfo['id'],
                'a.delete_flag' => 0,
                'b.delete_flag' => 0,
                'c.delete_flag' => 0,
            ])->get();

        $logData = [];
        $contentstorageManageData = [];
        if (!empty($productContent)) {
            foreach ($productContent->toArray() as $pVal) {
                $condition = [
                    'storage_id' => $packageInfo['storage_id'],
                    'type_id' => $pVal['type_id'],
                    'delete_flag' => 0
                ];
                if ($data['is_use_shelf'] || !empty($packageInfo['shelf_id'])) {
                    $condition['shelf_id'] = $packageInfo['shelf_id'];
                    $condition['location_id'] = $packageInfo['location_id'];
                }

                $contentStorageManageInfo = StorageManageModel::query()->where($condition)->first();

                $contentNum = $packageInfo['num'] * $pVal['num'];

                $cost = $pVal['cost'];
                $lastStorageNum = $contentNum;
                $nextStorageNum = $contentNum;
                $virtualStorageNum = $contentNum;
                $contentStorageManageId = $contentStorageManageInfo['id'] ?? 0;
                if (!empty($contentStorageManageInfo)) {
                    $lastStorageNum = $contentStorageManageInfo['in_storage_num'];
                    $nextStorageNum = $contentStorageManageInfo['in_storage_num'] + $contentNum;
                    $virtualStorageNum = $contentStorageManageInfo['virtual_storage_num'] + $contentNum;
                    if ($method == 'out') {
                        $nextStorageNum = $contentStorageManageInfo['in_storage_num'] - $contentNum;
                        $virtualStorageNum = $contentStorageManageInfo['virtual_storage_num'] - $contentNum;
                    }
                    $contentstorageManageData[] = [
                        'id' => $contentStorageManageId,
                        'in_storage_num' => $nextStorageNum,
                        'virtual_storage_num' => $virtualStorageNum
                    ];
                    $cost = $contentStorageManageInfo['materiel_mean_cost'];
                } else {

                    if ($method == 'out') {
                        throw new \Exception('套餐' . $packageInfo['materiel_name'] . '-组件' . $pVal['materiel_name'] . '的当前仓库无库存（组件必须库存足够才可以出库）');
                    }
                    $contentStorageManageId = StorageManageModel::query()->insertGetId([
                        'materiel_class_id' => $pVal['materiel_class_id'],
                        'materiel_class_name' => $pVal['sec_class_name'],
                        'materiel_class_no' => $pVal['sec_class_no'],
                        'type_id' => $pVal['id'],
                        'materiel_name' => $pVal['materiel_name'],
                        'type_name' => $pVal['type_name'],
                        'materiel_no' => $pVal['materiel_no'],
                        'materiel_mean_cost' => $cost,
                        'storage_id' => $storageInfo['id'],
                        'storage_name' => $storageInfo['storage_name'],
                        'storage_address' => $storageInfo['storage_address'],
                        'in_storage_num' => $contentNum,
                        'alert_num' => 0,
                        'virtual_storage_num' => $contentNum,
                        'main_id' => $data['main_id'],
                        'in_storage_time' => $data['in_storage_time'],
                        'is_product_materiel' => $pVal['is_product_materiel'],
                        'created_at' => time(),
                        'shelf_id' => $packageInfo['shelf_id'],
                        'location_id' => $packageInfo['location_id'],
                    ]);
                }
                $batchInfo = [
                    'batch_cost' => $cost,
                    'main_id' => $data['main_id'],
                    'storage_manage_id' => $contentStorageManageId
                ];
                $batchNo = self::createBatchNo($batchInfo, $contentNum, $data['batch_title'], $method);
                $log = [
                    'curr_storage_manage_id' => $contentStorageManageId,
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'materiel_class_id' => $pVal['materiel_class_id'],
                    'materiel_class_name' => $pVal['sec_class_name'],
                    'materiel_class_no' => $pVal['sec_class_no'],
                    'materiel_type_id' => $pVal['id'],
                    'materiel_name' => $pVal['materiel_name'],
                    'type_name' => $pVal['type_name'],
                    'materiel_no' => $pVal['materiel_no'],
                    'operate_num' => $contentNum,
                    'last_storage_num' => $lastStorageNum,
                    'next_storage_num' => $nextStorageNum,
                    'materiel_mean_cost' => $cost,
                    'batch_no' => $batchNo,
                    'user_id' => $data['user_id'],
                    'main_id' => $data['main_id'],
                    'created_at' => time(),
                    'shelf_id' => $packageInfo['shelf_id'],
                    'location_id' => $packageInfo['location_id'],
                    'remark' => '',
                    'label_id' => $data['label_id'] ?? 0,
                    'label_name' => $data['label_name'] ?? '',
                    'type' => $data['operation_type'],
                    'all_id_type' => $data['all_id_type'],
                    'all_id' => $data['all_id'] ?? 0,
                    'is_use_packages_module' => 1,
                    'general_remarks' => !empty($data['general_remarks']) ? $data['general_remarks'] : '',
                    'product_sell_price' => $packageInfo['sell_price'],
                    'product_type_id' => $packageInfo['id'],
                    'product_operate_num' => $packageInfo['num']
                ];

                if ($method == 'in') {//入库
                    $log['in_storage_time'] = $data['in_storage_time'];
                    $log ['supplier_id'] = $packageInfo['supplier_id'] ?? 0;
                    $inLogId = LogInStorageModel::query()->insertGetId($log);
                    MessageService::sendInSms(
                        '',
                        $pVal['materiel_name'],
                        $pVal['type_name'],
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $data,
                        $contentNum,
                        $nextStorageNum,
                        $inLogId
                    );

                } else {//出库
                    $log['sell_price'] = $pVal['selling_price'] ?? 0;
                    $log['client_id'] = $packageInfo['client_id'] ?? 0;
                    $log['out_storage_time'] = $data['in_storage_time'];
                    $log['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
                    $outLogId = LogOutStorageModel::query()->insertGetId($log);
                    MessageService::sendAlertSms(
                        $pVal['materiel_name'],
                        $pVal['type_name'],
                        $contentStorageManageInfo['in_storage_num'],
                        $contentStorageManageInfo['alert_num'],
                        $data,
                        $storageInfo['id'],
                        $storageInfo['storage_name'],
                        $contentNum
                    );

                    MessageService::sendShortSms(
                        $pVal['materiel_name'],
                        $pVal['type_name'],
                        $contentStorageManageInfo['in_storage_num'],
                        $data,
                        $storageInfo['storage_name'],
                        $storageInfo['id']
                    );
                    MessageService::sendOutSms(
                        $pVal['materiel_name'],
                        $pVal['type_name'],
                        0,
                        $storageInfo['storage_name'],
                        $contentNum,
                        $data,
                        $storageInfo['id'],
                        $contentStorageManageInfo['alert_num'],
                        $outLogId
                    );

                }
                //$logData[] = $log;
            }

            if (!empty($contentstorageManageData)) {
                batch()->update(new StorageManageModel, $contentstorageManageData, 'id');
            }
            /* if (!empty($logData)) {
                 if ($method == 'in') {
                     LogInStorageModel::query()->insert($logData);
                 } else {
                     LogOutStorageModel::query()->insert($logData);
                 }

             }*/
        }
    }

    public static function getIdentifyStorageCode($userInfo, $data)
    {
        $query = StorageManageModel::query()
            ->select(
                'a.id as storage_manage_id',
                'c.id as storage_id',
                'd.id as shelf_id',
                'e.id as location_id',
                'c.storage_name',
                'c.storage_address',
                'd.shelf_name',
                'e.location_name',
                'b.materiel_name',
                'b.materiel_no',
                'b.type_name',
                'b.is_use_serial',
                'b.is_product_materiel',
                'b.id as materiel_type_id',
                'b.materiel_img',
                'b.selling_price',
                'b.cost',
                'b.materiel_unit',
                'h.id as f_class_id',
                'h.class_name as f_class_name',
                'g.id as s_class_id',
                'g.class_name as s_class_name',
                'c.main_id',
                'c.user_id'
            )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('storage as c', 'c.id', '=', 'a.storage_id')
            ->leftJoin('storage_shelf as d', 'd.id', '=', 'a.shelf_id')
            ->leftJoin('storage_shelf_location as e', 'e.id', '=', 'a.location_id')
            ->leftJoin('materiel_class as g', 'b.materiel_class_id', '=', 'g.id')
            ->leftJoin('materiel_class as h', 'h.id', '=', 'g.parent_id');
        $standardnumInfo = StorageShelfLocationModel::query()
            ->where([
                'status' => 1,
                ['standard_num', '>', 0]
            ]);
        $manageInfo = StorageManageModel::query()
            ->where([
                'delete_flag' => 0,
                ['in_storage_num', '>', 0]
            ]);
        switch ($data['type']) {
            case 'warehouse'://仓库码
                if (!empty($data['click_type'])) {
                    $query->addSelect('in_storage_num');
                    $query->where('a.type_id', $data['type_id']);
                    $manageInfo->where('type_id', $data['type_id']);
                } else {
                    $query->addSelect(DB::raw("SUM(in_storage_num) AS in_storage_num"));
                    $query->groupBy('a.type_id');
                }
                $standardnumInfo->where('storage_id', $data['id']);
                $manageInfo->where('storage_id', $data['id']);
                $query->where('a.storage_id', $data['id']);
                break;
            case 'location'://库位
                $query->addSelect("in_storage_num");
                $query->groupBy('a.type_id');
                $query->where('a.location_id', $data['id']);
                $standardnumInfo->where('id', $data['id']);
                $manageInfo->where('location_id', $data['id']);
                if (!empty($data['type_id'])) {
                    $query->where('a.type_id', $data['type_id']);
                    $manageInfo->where('type_id', $data['type_id']);
                }
                break;
            case 'shelf';//货架
                if (!empty($data['click_type'])) {
                    $query->addSelect('in_storage_num');
                    $query->where('a.type_id', $data['type_id']);
                    $manageInfo->where('type_id', $data['type_id']);
                } else {
                    $query->addSelect(DB::raw("SUM(in_storage_num) AS in_storage_num"));
                    $query->groupBy('a.type_id');
                }
                $query->where('a.shelf_id', $data['id']);
                $standardnumInfo->where('shelf_id', $data['id']);
                $manageInfo->where('shelf_id', $data['id']);
                break;
        }
        $storaglist = [];
        $storaglist['standard_num'] = $standardnumInfo->sum('standard_num') ?? 0;
        $storaglist['total_num'] = $manageInfo->sum('in_storage_num') ?? 0;
        $list = $query->where([
            'a.delete_flag' => 0,
            'b.delete_flag' => 0,
            'c.delete_flag' => 0,
            'g.delete_flag' => 0,
            'h.delete_flag' => 0,
            'd.status' => 1,
            'e.status' => 1,
        ])->get();
        if (!empty($list->toArray())) {
            $isShareStore = 0;
            if (!empty($userInfo)) {
                if ($userInfo['main_id'] != $list->toArray()[0]['main_id']) {
                    return fail('', '请登录第三方扫码进行查看');
                }
                $isShareStore = AdminAddendumModel::query()
                    ->where('main_id', $userInfo['main_id'])
                    ->value('is_share_store');
            }
            foreach ($list->toArray() as $key => $value) {
                $isOperate = 0;
                if (!empty($userInfo)) {
                    if (empty($value['user_id']))
                        $value['user_id'] = $value['main_id'];
                    $value['nickname'] = AdminModel::query()
                        ->where('id', $value['user_id'])->value('nickname');
                    if ($userInfo['user_id'] == $userInfo['main_id']) {
                        $isOperate = 1;
                    } else {
                        if ($isShareStore) {
                            $isOperate = 1;
                        } else {
                            $storageIdArr = CommonService::getMultiUser($userInfo);
                            if (in_array($value['storage_id'], $storageIdArr)) {
                                $isOperate = 1;
                            } else {
                                $isOperate = 0;
                            }
                        }
                    }
                }
                if (!empty($data['click_type'])) {
                    $storaglist['f_class_name'] = $value['f_class_name'];
                    $storaglist['s_class_name'] = $value['s_class_name'];
                    $storaglist['f_class_id'] = $value['f_class_id'];
                    $storaglist['s_class_id'] = $value['s_class_id'];
                    $storaglist['materiel_name'] = $value['materiel_name'];
                    $storaglist['type_name'] = $value['type_name'];
                    $storaglist['materiel_no'] = $value['materiel_no'];
                    $storaglist['storage_list'][] = [
                        'is_operate' => $isOperate,
                        'storage_manage_id' => $value['storage_manage_id'],
                        'selling_price' => $value['selling_price'],
                        'cost' => $value['cost'],
                        'materiel_unit' => $value['materiel_unit'],
                        'in_storage_num' => $value['in_storage_num'],
                        'is_use_serial' => $value['is_use_serial'],
                        'is_product_materiel' => $value['is_product_materiel'],
                        'materiel_type_id' => $value['materiel_type_id'],
                        'storage_name' => $value['storage_name'],
                        'shelf_name' => $value['shelf_name'],
                        'location_name' => $value['location_name'],
                        'storage_id' => $value['storage_id'],
                        'shelf_id' => $value['shelf_id'],
                        'location_id' => $value['location_id'],
                        'f_class_name' => $value['f_class_name'],
                        'f_class_id' => $value['f_class_id'],
                        's_class_name' => $value['s_class_name'],
                        's_class_id' => $value['s_class_id'],
                        'materiel_name' => $value['materiel_name'],
                        'type_name' => $value['type_name'],
                        'materiel_no' => $value['materiel_no']
                    ];
                } else {
                    $storaglist['storage_name'] = $value['storage_name'];
                    $storaglist['storage_address'] = $value['storage_address'];
                    $storaglist['shelf_name'] = $value['shelf_name'];
                    $storaglist['location_name'] = $value['location_name'];
                    $storaglist['nickname'] = $value['nickname'];
                    $storaglist['storage_id'] = $value['storage_id'];
                    $storaglist['shelf_id'] = $value['shelf_id'];
                    $storaglist['location_id'] = $value['location_id'];
                    $storaglist['goods_list'][] = [
                        'is_operate' => $isOperate,
                        'storage_manage_id' => $value['storage_manage_id'],
                        'materiel_name' => $value['materiel_name'],
                        'materiel_no' => $value['materiel_no'],
                        'type_name' => $value['type_name'],
                        'materiel_img' => $value['materiel_img'],
                        'selling_price' => $value['selling_price'],
                        'cost' => $value['cost'],
                        'materiel_unit' => $value['materiel_unit'],
                        'in_storage_num' => $value['in_storage_num'],
                        'is_use_serial' => $value['is_use_serial'],
                        'is_product_materiel' => $value['is_product_materiel'],
                        'materiel_type_id' => $value['materiel_type_id'],
                        'storage_name' => $value['storage_name'],
                        'shelf_name' => $value['shelf_name'],
                        'location_name' => $value['location_name'],
                        'storage_id' => $value['storage_id'],
                        'shelf_id' => $value['shelf_id'],
                        'location_id' => $value['location_id']
                    ];
                }
            }
        } else {
            $info = [];
            switch ($data['type']) {
                case 'warehouse'://仓库码
                    $info = StorageModel::query()
                        ->select(
                            'a.id as torage_id',
                            'storage_name',
                            'nickname',
                            'storage_address'
                        )
                        ->from('storage as a')
                        ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
                        ->where(['a.id' => $data['id']])->first();
                    break;
                case 'location'://库位
                    $info = StorageShelfLocationModel::query()
                        ->select(
                            'a.id as location_id',
                            'location_name',
                            'shelf_id',
                            'shelf_name',
                            'a.storage_id',
                            'storage_name',
                            'nickname',
                            'storage_address'
                        )
                        ->from('storage_shelf_location as a')
                        ->leftJoin('storage_shelf as b', 'b.id', '=', 'a.shelf_id')
                        ->leftJoin('storage as c', 'c.id', '=', 'a.storage_id')
                        ->leftJoin('admin as d', 'd.id', '=', 'c.user_id')
                        ->where(['a.id' => $data['id']])->first();
                    break;
                case 'shelf';//货架
                    $info = StorageShelfModel::query()
                        ->select(
                            'a.id as shelf_id',
                            'shelf_name',
                            'storage_id',
                            'storage_name',
                            'nickname',
                            'storage_address'
                        )
                        ->from('storage_shelf as a')
                        ->leftJoin('storage as b', 'b.id', '=', 'a.storage_id')
                        ->leftJoin('admin as c', 'c.id', '=', 'b.user_id')
                        ->where(['a.id' => $data['id']])->first();
                    break;
            }

            $storaglist['storage_name'] = $info['storage_name'] ?? '';
            $storaglist['storage_address'] = $info['storage_address'] ?? '';
            $storaglist['shelf_name'] = $info['shelf_name'] ?? '';
            $storaglist['location_name'] = $info['location_name'] ?? '';
            $storaglist['nickname'] = $info['nickname'] ?? '';
            $storaglist['storage_id'] = $info['storage_id'] ?? '';
            $storaglist['shelf_id'] = $info['shelf_id'] ?? '';
            $storaglist['location_id'] = $info['location_id'] ?? '';
            $storaglist['goods_list'] = [];
        }

        if (!empty($data['storage_id'])) {
            $standardnumInfo->where('storage_id', $data['storage_id']);
            $manageInfo->where('storage_id', $data['storage_id']);
        } elseif (!empty($data['shelf_id'])) {
            $standardnumInfo->where('shelf_id', $data['shelf_id']);
            $manageInfo->where('shelf_id', $data['shelf_id']);
        } elseif (!empty($data['location_id'])) {
            $standardnumInfo->where('id', $data['location_id']);
            $manageInfo->where('id', $data['location_id']);
        }


        return success($storaglist);
    }

    /**
     *库存列表-仓库模式
     * Author: zlf
     * Created at 2024/5/9 16:06
     * @param $parentId
     * @param $data
     * @param $storageIdArr
     * @return array|\Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    static public function warehouseInventoryList($parentId, $data, $storageIdArr = [])
    {
        $keyword = empty($data['keyword']) ? '' : $data['keyword'];
        $condition = [];
        if (!empty($data['materiel_class_id'])) {
            $condition['c.id'] = ['EQ' => $data['materiel_class_id']];
        }

        if (isset($data['is_product_materiel'])) {
            $condition['a.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        if (isset($data['is_product_storage'])) {
            $condition['e.is_product_storage'] = ['EQ' => $data['is_product_storage']];
        }
        $result = SELF::warehouseModelList($parentId, $keyword, $condition, $data, $storageIdArr);

        return $result;
    }

    /**
     *库存列表-仓库模式
     * Author: zlf
     * Created at 2024/5/9 16:06
     * @param $parentId
     * @param $data
     * @param $storageIdArr
     * @return array|\Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    static public function newInventoryList($parentId, $data, $storageIdArr = [])
    {
        $keyword = empty($data['keyword']) ? '' : $data['keyword'];
        $condition = [];
        if (!empty($data['materiel_class_id'])) {
            $condition['c.id'] = ['EQ' => $data['materiel_class_id']];
        }

        if (isset($data['is_product_materiel'])) {
            $condition['a.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        if (isset($data['is_product_storage'])) {
            $condition['e.is_product_storage'] = ['EQ' => $data['is_product_storage']];
        }
        $result = SELF::newModelList($parentId, $keyword, $condition, $data, $storageIdArr);
        $goodsList = StorageManageModel::query()
            ->select('b.materiel_name', 'b.materiel_img')
            ->from('storage_manage as a')
            ->Join('materiel_type as b', 'a.type_id', '=', 'b.id')
            ->Join('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
            ->where([
                "a.delete_flag" => 0,
                "b.delete_flag" => 0,
                "c.delete_flag" => 0,
                "a.main_id" => $data["main_id"],
            ])->where(function ($query) use ($keyword,$data) {
                if (!empty($keyword)) {
                    if (strpos($keyword, 'T-') !== false) {
                        $keyword = explode('T-', $keyword);
                        $keyword = trim($keyword[1]);
                    }
                    $query->orWhere('b.materiel_name', 'like', '%' . $keyword . '%');
                    $query->orWhere('b.type_name', 'like', '%' . $keyword . '%');
                    $query->orWhere('b.materiel_no', 'like', '%' . $keyword . '%');
                    $query->orWhere('b.two_materiel_name', 'like', '%' . $keyword . '%');
                }
                if(!empty($data['storage_id'])){
                    $query->where('a.storage_id', $data['storage_id']);
                }
                if(!empty($data['f_class_id'])){
                    $query->where('c.parent_id', $data['f_class_id']);
                }
                if(!empty($data['materiel_class_id'])){
                    $query->where('b.materiel_class_id', $data['materiel_class_id']);
                }
            })->groupBy('b.materiel_name')
            ->paginate($data['pageSize'], ['*'], '', $data['currentPage'])->toArray();
        $totalManageNum = 0;
        if (!empty($goodsList['data'])) {
            $goodsData = $goodsList['data'];
            foreach ($goodsData as &$value) {
                $totalGoodsNum = 0;
                $totalSellPrice = 0;
                $totalCostPrice = 0;
                foreach ($result as $rVal) {
                    if ($value['materiel_name'] == $rVal['materiel_name']) {
                        $value['goods_list'][] = $rVal;
                        $totalGoodsNum += $rVal['in_storage_num'];
                        $totalSellPrice += $rVal['in_storage_num'] * $rVal['selling_price'];
                        $totalCostPrice += $rVal['in_storage_num'] * $rVal['materiel_mean_cost'];
                    }
                }
                $value['total_goods_num'] = $totalGoodsNum;
                $value['total_sell_price'] = $totalSellPrice;
                $value['total_cost_price'] = $totalCostPrice;
                $totalManageNum += $value['total_goods_num'];
            }

            $gData=[];
            foreach ($goodsData as &$item) {
                if (!empty($item['goods_list'])) { // 根据需要调整条件
                    $gData[] = $item;
                }
            }
            $goodsList['data'] = $gData;
        }
        $goodsList['total_num'] = $totalManageNum;
        return $goodsList;
    }


    /**
     *库存列表-库存模式
     * Author: zlf
     * Created at 2024/5/9 16:26
     * @param $parentId
     * @param $keyword
     * @param $condition
     * @param $data
     * @param $storageIdArr
     * @return array
     */
    private static function WarehouseModelList($parentId, $keyword, $condition, $data, $storageIdArr = [])
    {
        $query = StorageManageModel::query()
            ->select(
                'a.id',
                'b.materiel_name',
                'a.type_id',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'a.materiel_mean_cost',
                'a.storage_id',
                'e.storage_name',
                'e.storage_address',
                'a.alert_num',
                'b.is_product_materiel',
                'b.selling_price',
                'b.lower_selling_price',
                'b.remark',
                'b.is_use_serial',
                'b.bar_code',
                'b.materiel_unit',
                'a.sort_flag',
                'time_warning_flag',
                'd.id as f_class_id',
                'd.class_name as f_class_name',
                'd.class_no as f_class_no',
                'c.id as s_class_id',
                'c.class_name as s_class_name',
                'c.class_no as s_class_no',
            )->from('storage_manage as a')
            ->leftJoin("materiel_type as b", "b.id", "=", "a.type_id")
            ->leftJoin('materiel_class as c', 'b.materiel_class_id', '=', 'c.id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
            ->leftJoin('storage as e', 'e.id', '=', 'storage_id')
            ->where($parentId)
            ->where([
                'a.delete_flag' => 0,
                'b.delete_flag' => 0,
                'c.delete_flag' => 0,
                'e.delete_flag' => 0,
            ]);
        if (!empty($data['is_zero'])) {
            $query->where('a.in_storage_num', '!=', 0);
        }
        if (!empty($data['f_class_id'])) {
            $secClassId = MaterielClassModel::query()
                ->where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id'],
                    'parent_id' => $data['f_class_id']
                ])->pluck('id');
            if (!empty($secClassId)) {
                $query->whereIn('b.materiel_class_id', $secClassId->toArray());
            }
        }
        if (!empty($keyword)) {
            switch ($data['sel_type']) {
                case 1://商品名称查询
                    if (strpos($keyword, 'T-') !== false) {
                        $keyword = explode('T-', $keyword);
                        $keyword = trim($keyword[1]);
                    }
                    $query->where('b.materiel_name', 'like', '%' . $keyword . '%');
                    break;
                case 2://商品类型查询
                    $query->where('b.type_name', 'like', '%' . $keyword . '%');
                    break;
                case 3://商品编号查询
                    $query->where('b.materiel_no', 'like', '%' . $keyword . '%');
                    break;
                case 4://批次号查询
                    $storageBatchInfo = StorageBatchModel::query()
                        ->select('storage_id', 'type_id')
                        ->from('storage_batch as a')
                        ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                        ->where([
                            'b.main_id' => $data['main_id'],
                            'a.delete_flag' => 0,
                            'b.delete_flag' => 0
                        ])->where('batch_no', 'like', '%' . $keyword . '%')
                        ->first();
                    if (!empty($storageBatchInfo)) {
                        $storageBatchInfo = $storageBatchInfo->toArray();
                    } else {
                        $storageBatchInfo = [
                            'storage_id' => '',
                            'type_id' => ''
                        ];
                    }
                    $query->where($storageBatchInfo);
                    break;
                case 5://序列号查询
                    $serialNumberInfo = SerialNumberModel::query()
                        ->select('storage_id', 'type_id')
                        ->from('serial_number as a')
                        ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_manage_id')
                        ->where([
                            'b.main_id' => $data['main_id'],
                            'b.delete_flag' => 0
                        ])
                        ->where('serial_no', 'like', '%' . $keyword . '%')
                        ->first();
                    if (!empty($serialNumberInfo)) {
                        $serialNumberInfo = $serialNumberInfo->toArray();
                    } else {
                        $serialNumberInfo = [
                            'storage_id' => '',
                            'type_id' => ''
                        ];
                    }
                    $query->where($serialNumberInfo);
                    break;
                default:
                    $query->where('b.materiel_name', 'like', '%' . $keyword . '%');
                    break;
            }
        };
        if (!empty($storageIdArr)) {
            $query->whereIn('storage_id', $storageIdArr);
        }
        if (!empty($data['storage_id'])) {
            $query->where('a.storage_id', $data['storage_id']);
        }
        if (!empty($data['materiel_class_id'])) {
            $query->where('b.materiel_class_id', $data['materiel_class_id']);
        }
        if (!empty($condition)) {
            $query->where($condition);
        }
        $list = [];
        $storageMangeList = [];
        $query->groupBy('type_id')->groupBy('storage_id');
        $totalNum = 0;
        if (!empty($query->get()->toArray())) {
            $list = $query->addSelect('in_storage_num')
                ->get()->toArray();
            foreach ($list as $lVal) {
                $totalNum += $lVal['in_storage_num'];
            }
        }
        if ($data['order_type'] == 1) {//库存排序
            if (!empty($list)) {
                $storageMangeList = $list;
            }
        } else {
            if ($data['order_type'] == 2) {//商品名称排序
                $query->orderBy('b.materiel_name', $data['order_by']);
                //$query->orderByRaw("CONVERT('materiel_name' USING gbk) COLLATE gbk_chinese_ci ASC");
            } else {//默认排序
                $query->orderBy('sort_flag', 'desc');
            }

            $list = $query->paginate($data['pageSize'], ['*'], '', $data['currentPage'])->toArray();
            $storageMangeList = $list['data'];
        }
        if (!empty($storageMangeList)) {
            foreach ($storageMangeList as &$val) {
                $info = StorageManageModel::query()
                    ->select(
                        DB::raw("SUM(in_storage_num) AS in_num"),
                        DB::raw("SUM(virtual_storage_num) AS virtual_num"),
                    )->where([
                        'storage_id' => $val['storage_id'],
                        'type_id' => $val['type_id'],
                        'main_id' => $data['main_id']
                    ])->first();
                $val['in_storage_num'] = !empty($info['in_num']) ? $info['in_num'] : 0;
                $val['virtual_storage_num'] = !empty($info['virtual_num']) ? $info['virtual_num'] : 0;
                if (!empty($val['materiel_img'])) {
                    if (strpos($val['materiel_img'], ',') !== false) {
                        $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                            return $v !== '';
                        });
                        $val['materiel_img'] = $materielImg[0] ?? '';
                    }
                }
                $tNum = '0套';
                $val['forecasting_num'] = 0;
                $val['product_content'] = [];
                if ($val['is_product_materiel'] == 1) {
                    $productList = MaterielProductContentModel::select(
                        'a.id',
                        'b.materiel_name',
                        'b.type_name',
                        'b.materiel_img',
                        'b.materiel_no',
                        'a.product_id',
                        'a.num',
                        'a.price',
                        'a.type_id',
                        'a.total_price'
                    )
                        ->from('materiel_product_content as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                        ->where([
                            'a.delete_flag' => 0,
                            'b.delete_flag' => 0,
                            'a.product_id' => $val['type_id']
                        ])->get();

                    if (!empty($productList->toArray())) {
                        $productList = $productList->toArray();
                        foreach ($productList as &$v) {
                            if (!empty($v['materiel_img'])) {
                                $materielImg = array_filter(explode(',', $v['materiel_img']), function ($v) {
                                    return $v !== '';
                                });
                                $v['materiel_img'] = $materielImg[0];
                            }
                        }
                        $tNum = self::forecastingOfProductUsefulNum($val['type_id']);
                    } else {
                        $productList = [];
                    }
                    $val['product_content'] = $productList;
                    $val['forecasting_num'] = $tNum;
                } else {
                    $val['forecasting_num'] = $tNum;
                }
                if (!$data['user_type']) {
                    $val['is_operate'] = 1;
                } else {
                    if ($data['is_share_storage_operate']) {
                        $val['is_operate'] = 1;
                    } else {
                        if (in_array($val['storage_id'], $storageIdArr)) {
                            $val['is_operate'] = 1;
                        } else {
                            $val['is_operate'] = 0;
                        }
                    }
                }
            }
            if ($data['order_type'] == 1) {//库存排序
                $paramSort = array_column($storageMangeList, 'in_storage_num');
                $sort = $data['order_by'] == 'desc' ? SORT_DESC : SORT_ASC;
                array_multisort($paramSort, $sort, $storageMangeList);
            }
        }
        $storageMangeList = !empty($storageMangeList) ? $storageMangeList : [];
        if (isset($list['data'])) {//默认排序，系统分页
            $list['total_num'] = $totalNum;
            $list['data'] = $storageMangeList;
        } else {
            $currentPage = $data['currentPage'];
            $result = array_slice(array_values($storageMangeList), --$data['currentPage'] * $data['pageSize'], $data['pageSize']);
            $list = [
                'total' => count($storageMangeList),
                'current_page' => $currentPage,
                'next_page_url' => count($result) < $data['pageSize'] ? null : config('app.url') . "storage_manage_list?=" . ($data['currentPage'] + 1),
                'prev_page_url' => $currentPage == 1 ? null : config('app.url') . "storage_manage_list?=" . ($currentPage - 1),
                "path" => config('app.url') . "storage_manage_list",
                "to" => $currentPage * $data['pageSize'],
                'data' => array_values($result),
                "per_page" => $data['pageSize']
            ];
        }
        return $list;
    }

    /**
     *库存列表-库存模式
     * Author: zlf
     * Created at 2024/5/9 16:26
     * @param $parentId
     * @param $keyword
     * @param $condition
     * @param $data
     * @param $storageIdArr
     * @return array
     */
    private static function newModelList($parentId, $keyword, $condition, $data, $storageIdArr = [])
    {
        $query = StorageManageModel::query()
            ->select(
                'a.id',
                'b.materiel_name',
                'a.type_id',
                'b.type_name',
                'b.materiel_no',
                'b.materiel_img',
                'a.materiel_mean_cost',
                'a.storage_id',
                'e.storage_name',
                'e.storage_address',
                'a.alert_num',
                'b.is_product_materiel',
                'b.selling_price',
                'b.lower_selling_price',
                'b.remark',
                'b.is_use_serial',
                'b.bar_code',
                'b.materiel_unit',
                'a.sort_flag',
                'time_warning_flag',
                'd.id as f_class_id',
                'd.class_name as f_class_name',
                'd.class_no as f_class_no',
                'c.id as s_class_id',
                'c.class_name as s_class_name',
                'c.class_no as s_class_no',
                'f.shelf_name',
                'g.location_name',
                'b.goods_supplier_name',
                'b.goods_client_name',
                'a.shelf_id',
                'a.location_id'
            )->from('storage_manage as a')
            ->leftJoin("materiel_type as b", "b.id", "=", "a.type_id")
            ->leftJoin('materiel_class as c', 'b.materiel_class_id', '=', 'c.id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->leftJoin('storage_shelf as f', 'f.id', '=', 'a.shelf_id')
            ->leftJoin('storage_shelf_location as g', 'g.id', '=', 'a.location_id')
            ->where($parentId)
            ->where([
                'a.delete_flag' => 0,
                'b.delete_flag' => 0,
                'c.delete_flag' => 0,
                'e.delete_flag' => 0,
                'f.status' => 1,
                'g.status' => 1,
            ]);
        if (!empty($data['is_zero'])) {
            $query->where('a.in_storage_num', '>', 0);
        }
        if (!empty($data['f_class_id'])) {
            $secClassId = MaterielClassModel::query()
                ->where([
                    'delete_flag' => 0,
                    'main_id' => $data['main_id'],
                    'parent_id' => $data['f_class_id']
                ])->pluck('id');
            if (!empty($secClassId)) {
                $query->whereIn('b.materiel_class_id', $secClassId->toArray());
            }
        }
        if (!empty($keyword)) {
            $query->where(function ($query) use ($keyword) {
                if (!empty($keyword)) {
                    if (strpos($keyword, 'T-') !== false) {
                        $keyword = explode('T-', $keyword);
                        $keyword = trim($keyword[1]);
                    }
                    $query->orWhere('b.materiel_name', 'like', '%' . $keyword . '%');
                    $query->orWhere('b.type_name', 'like', '%' . $keyword . '%');
                    $query->orWhere('b.materiel_no', 'like', '%' . $keyword . '%');
                    $query->orWhere('b.two_materiel_name', 'like', '%' . $keyword . '%');
                }
            });
        };
        if (!empty($storageIdArr)) {
            $query->whereIn('a.storage_id', $storageIdArr);
        }
        if (!empty($data['storage_id'])) {
            $query->where('a.storage_id', $data['storage_id']);
        }
        if (!empty($data['materiel_class_id'])) {
            $query->where('b.materiel_class_id', $data['materiel_class_id']);
        }
        if(!empty($data['f_class_id'])){
            $query->where('c.parent_id', $data['f_class_id']);
        }
        if (!empty($condition)) {
            $query->where($condition);
        }
        $list = [];
        $storageMangeList = [];
        //$query->groupBy('type_id')->groupBy('storage_id');
        $totalNum = 0;
        if (!empty($query->get()->toArray())) {
            $list = $query->addSelect('in_storage_num')
                ->get()->toArray();
            foreach ($list as $lVal) {
                $totalNum += $lVal['in_storage_num'];
            }
        }
        if ($data['order_type'] == 1) {//库存排序
            if (!empty($list)) {
                $storageMangeList = $list;
            }
        } else {
            if ($data['order_type'] == 2) {//商品名称排序
                $query->orderBy('b.materiel_name', $data['order_by']);
                //$query->orderByRaw("CONVERT('materiel_name' USING gbk) COLLATE gbk_chinese_ci ASC");
            } else {//默认排序
                $query->orderBy('sort_flag', 'desc');
            }
        }
        $storageMangeList = $query->get()->toArray();
        if (!empty($storageMangeList)) {
            foreach ($storageMangeList as &$val) {

                if (!empty($val['materiel_img'])) {
                    if (strpos($val['materiel_img'], ',') !== false) {
                        $materielImg = array_filter(explode(',', $val['materiel_img']), function ($v) {
                            return $v !== '';
                        });
                        $val['materiel_img'] = $materielImg[0] ?? '';
                    }
                }
                $tNum = '0套';
                $val['forecasting_num'] = 0;
                $val['product_content'] = [];
                if ($val['is_product_materiel'] == 1) {
                    $productList = MaterielProductContentModel::select(
                        'a.id',
                        'b.materiel_name',
                        'b.type_name',
                        'b.materiel_img',
                        'b.materiel_no',
                        'a.product_id',
                        'a.num',
                        'a.price',
                        'a.type_id',
                        'a.total_price'
                    )
                        ->from('materiel_product_content as a')
                        ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                        ->where([
                            'a.delete_flag' => 0,
                            'b.delete_flag' => 0,
                            'a.product_id' => $val['type_id']
                        ])->get();

                    if (!empty($productList->toArray())) {
                        $productList = $productList->toArray();
                        foreach ($productList as &$v) {
                            if (!empty($v['materiel_img'])) {
                                $materielImg = array_filter(explode(',', $v['materiel_img']), function ($v) {
                                    return $v !== '';
                                });
                                $v['materiel_img'] = $materielImg[0];
                            }
                        }
                        $tNum = self::forecastingOfProductUsefulNum($val['type_id']);
                    } else {
                        $productList = [];
                    }
                    $val['product_content'] = $productList;
                    $val['forecasting_num'] = $tNum;
                } else {
                    $val['forecasting_num'] = $tNum;
                }
                if (!$data['user_type']) {
                    $val['is_operate'] = 1;
                } else {
                    if ($data['is_share_storage_operate']) {
                        $val['is_operate'] = 1;
                    } else {
                        if (in_array($val['storage_id'], $storageIdArr)) {
                            $val['is_operate'] = 1;
                        } else {
                            $val['is_operate'] = 0;
                        }
                    }
                }
            }
            if ($data['order_type'] == 1) {//库存排序
                $paramSort = array_column($storageMangeList, 'in_storage_num');
                $sort = $data['order_by'] == 'desc' ? SORT_DESC : SORT_ASC;
                array_multisort($paramSort, $sort, $storageMangeList);
            }
        }
        $storageMangeList = !empty($storageMangeList) ? $storageMangeList : [];
        return $storageMangeList;
    }

    static public function warehouseStorageManageIn($data)
    {
        $storageInfo = StorageModel::query()
            ->select(
                'a.id',
                'b.id as shelf_id',
                'c.id  as location_id',
                'storage_name',
                'storage_address'
            )->from('storage as a')
            ->leftJoin('storage_shelf as b', 'storage_id', '=', 'a.id')
            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
            ->where([
                'a.id' => $data['storage_id'],
                'a.main_id' => $data['main_id'],
                'b.shelf_type' => 1,
                'c.location_type' => 1,
                'a.delete_flag' => 0,
                'b.status' => 1,
                'c.status' => 1,
            ])->first();
        if (!empty($storageInfo)) {
            $storageInfo = $storageInfo->toArray();
        } else {
            return ['code' => 1, 'msg' => '没有到了，默认的仓库信息！', 'data' => ''];
        }
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.type_id',
            'in_storage_num',
            'virtual_storage_num',
            'materiel_mean_cost',
            'b.type_name',
            'b.materiel_name',
            'b.materiel_no',
            'a.materiel_class_id',
            'c.class_name',
            'c.class_no',
            'a.storage_id',
            'd.storage_name',
            'd.storage_address',
            'shelf_id',
            'location_id'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'a.type_id', '=', 'b.id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'a.materiel_class_id')
            ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
            ->where([
                'a.storage_id' => $storageInfo['id'],
                'a.shelf_id' => $storageInfo['shelf_id'],
                'a.location_id' => $storageInfo['location_id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
                'a.type_id' => $data['type_id']
            ])->first();
        DB::beginTransaction();
        try {
            if (!empty($storageManageInfo)) {
                $storageManageInfo = $storageManageInfo->toArray();
                StorageManageModel::where('id', $storageManageInfo['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + ' . $data['num']),
                        //'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num'])
                    ]);
            } else {
                $materielTypeInfo = MaterielTypeModel::query()
                    ->select('a.*', 'class_no')
                    ->from('materiel_type as a')
                    ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                    ->where([
                        'a.id' => $data['type_id'],
                        'a.main_id' => $data['main_id'],
                        'a.delete_flag' => 0
                    ])->first();
                if (empty($materielTypeInfo))
                    throw new \Exception('没有找到，商品信息！');
                $materielTypeInfo = $materielTypeInfo->toArray();
                $id = StorageManageModel::insertGetId([
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'materiel_mean_cost' => $materielTypeInfo['cost'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $data['num'],
                    'alert_num' => 0,
                    'virtual_storage_num' => 0,
                    'main_id' => $data['main_id'],
                    'in_storage_time' => time(),
                    'is_product_materiel' => $materielTypeInfo['is_product_materiel'],
                    'created_at' => time(),
                    'shelf_id' => $storageInfo['shelf_id'],
                    'location_id' => $storageInfo['location_id']
                ]);
                $storageManageInfo = StorageManageModel::query()->where('id', $id)->first();
            }
            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            $checkBatchNo = StorageBatchModel::where('main_id', $data['main_id'])
                ->where('batch_no', $batchNo)->first();

            do {
                $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
            } while (!empty($checkBatchNo));

            $batchId = MaterielService::createBatchInfoGetId(
                $batchNo,
                $storageManageInfo['id'],
                $storageManageInfo['materiel_mean_cost'],
                $data['num'],
                0,
                $data['main_id']
            );

            LogInstorageModel::insert([
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_type_id' => $storageManageInfo['type_id'],//物料id
                'batch_id' => $batchId,//物料id
                'materiel_name' => $storageManageInfo['materiel_name'],//物料名称
                'type_name' => $storageManageInfo['type_name'],//物料型号
                'materiel_no' => $storageManageInfo['materiel_no'],//物料编号
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],//物料二级分类主键名称
                'materiel_class_name' => $storageManageInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => $storageManageInfo['class_no'],//物料二级分类编号
                'type' => 2,//入库日志类型;0:入库;1:调拨入库;2:直接入库;
                'storage_id' => $storageManageInfo['storage_id'],//仓库主键id
                'storage_name' => $storageManageInfo['storage_name'],//仓库名
                'storage_address' => $storageManageInfo['storage_address'],//仓库地址
                'last_storage_id' => 0,//调拨前所在仓库id
                'operate_num' => $data['num'],//操作数量
                'last_storage_num' => 0,//操作前库存数
                'materiel_mean_cost' => empty($storageManageInfo) ? 0 : $storageManageInfo['materiel_mean_cost'],//物料均价
                'next_storage_num' => $storageManageInfo['in_storage_num'] + $data['num'],//操作后库存数
                'all_id_type' => 0,//单据类型;0:无;1:报溢;2:退货;3:采购;
                'in_storage_time' => time(),//入库时间
                'shelf_id' => $storageManageInfo['shelf_id'],
                'location_id' => $storageManageInfo['location_id'],
                'all_id' => 0,//单据id
                'user_id' => $data['user_id'],//操作人用户id
                'main_id' => $data['main_id'],//主账号id
                'remark' => empty($data['remark']) ? '' : $data['remark'],
                'label_id' => $data['label_id'],
                'label_name' => !empty($data['label_name']) ? $data['label_name'] : "",
                'created_at' => $data['time'],
            ]);

            MessageService::sendInSms(
                time(),
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data,
                $data['num'],
                $storageManageInfo['in_storage_num'] + $data['num']
            );

            $logData = '商品名称：' . $storageManageInfo['materiel_name'] . '（' . $storageManageInfo['materiel_no'] . '）' .
                '入库数量：' . $data['num'] . ' 仓库名：' . $storageManageInfo['storage_name'];
            CommonService::operateResult($data['user_id'], $data['time'], $data, $logData);
            CommonService::cancelAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('库存直接入库异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '直接入库失败！', 'data' => ''];
        }
    }

    static public function warehouseStorageManageOut($data)
    {
        $condtion = [
            'main_id' => $data['main_id'],
            'storage_id' => $data['storage_id'],
            'type_id' => $data['type_id'],
            'delete_flag' => 0,
            ['in_storage_num', '>', 0]
        ];
        $list = StorageManageModel::query()->where($condtion)
            ->orderBy('created_at', 'asc')->get();
        DB::beginTransaction();
        try {
            if (!empty($list->toArray())) {
                //有库存数量的
                $totalNum = StorageManageModel::query()
                    ->where($condtion)->sum('in_storage_num');
                if ($data['num'] >= $totalNum) {
                    //出库数量大于总的库存数据
                    StorageManageModel::query()
                        ->where($condtion)->update(['in_storage_num' => 0]);
                    $remainderNum = $data['num'] - $totalNum;
                    SELF::intertOutStorageLog($list->toArray(), $data, 0);
                    if (!empty($remainderNum)) {
                        //没有扣出的，最老的库存一直扣
                        StorageManageModel::query()
                            ->where(['id' => $list[0]['id']])
                            ->decrement('in_storage_num', $remainderNum);
                        SELF::intertOutStorageLog($forList[] = $list[0], $data, $remainderNum);
                    }

                } else {
                    //出库数量小于总的库存数据
                    $remainderNum = $data['num'];
                    foreach ($list as $key => $val) {
                        //出库数据大于单个库存的数据库存10，出库8
                        $remainderNum = $val['in_storage_num'] - $remainderNum;
                        if ($remainderNum >= 0) {
                            //单个库存大于等于了出库数量
                            $val->in_storage_num = $remainderNum;
                            SELF::intertOutStorageLog($forList[] = $val, $data, $remainderNum);
                            $val->save();
                            continue;
                        } else {
                            //单个库存小于了出库数量
                            $val->in_storage_num = 0;
                            SELF::intertOutStorageLog($forList[] = $val, $data, 0);
                            $val->save();
                        }
                    }

                }
            } else {//无库存数量的
                $info = StorageManageModel::query()
                    ->where([
                        'main_id' => $data['main_id'],
                        'storage_id' => $data['storage_id'],
                        'type_id' => $data['type_id'],
                        'delete_flag' => 0,
                    ])->orderBy('careated_at', 'asc')->first();
                $info->in_storage_num = $info->in_storage_num - $data['num'];
                SELF::intertOutStorageLog($forList[] = $info, $data, $info->in_storage_num);
                $info->save();
            }
            $storageManageInfo = StorageManageModel::query()->where([
                'main_id' => $data['main_id'],
                'storage_id' => $data['storage_id'],
                'type_id' => $data['type_id'],
                'delete_flag' => 0,
            ])->first();
            $logData = '商品名称：' . $storageManageInfo['materiel_name'] . '（' . $storageManageInfo['materiel_no'] . '）' .
                '出库数量：' . $data['num'] . ' 仓库名：' . $storageManageInfo['storage_name'];
            CommonService::operateResult($data['user_id'], $data['time'], $storageManageInfo, $logData);
            CommonService::setAlertFlag($data['main_id']);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (Exception $e) {
            DB::rollBack();
            Log::debug('直接出库异常:' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '出库失败！', 'data' => ''];
        }
    }

    private static function intertOutStorageLog($list, $data, $num = 0)
    {
        foreach ($list as $key => $val) {
            //出库操作记录日志
            LogOutstorageModel::insert([
                'type' => 2,//type;0:出库;1:调出;2:直接出库;
                'storage_id' => $val['storage_id'],
                'storage_name' => $val['storage_name'],
                'storage_address' => $val['storage_address'],
                'next_storage_id' => 0,
                'next_storage_name' => '',
                'next_storage_address' => '',
                'curr_storage_manage_id' => $val['id'],
                'materiel_class_id' => $val['materiel_class_id'],
                'materiel_class_name' => $val['materiel_class_name'],
                'materiel_class_no' => $val['materiel_class_no'],
                'materiel_type_id' => $val['type_id'],
                'materiel_name' => $val['materiel_name'],
                'type_name' => $val['type_name'],
                'materiel_no' => $val['materiel_no'],
                'operate_num' => $data['num'],
                'last_storage_num' => $val['in_storage_num'],
                'next_storage_num' => $num,
                'sell_price' => $val['materiel_mean_cost'],
                'materiel_mean_cost' => $val['materiel_mean_cost'],
                'remark' => empty($data['remark']) ? '' : $data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => $data['time'],
                'created_at' => $data['time'],
                'shelf_id' => $val['shelf_id'],
                'location_id' => $val['location_id'],
                'label_id' => $data['label_id'],
                'label_name' => !empty($data['label_name']) ? $data['label_name'] : '',
            ]);

            MessageService::sendAlertSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'],
                0,
                $data,
                $val['storage_id'],
                $val['storage_name'],
                $num
            );

            MessageService::sendShortSms(
                $val['materiel_name'],
                $val['type_name'],
                $num,
                $data,
                $val['storage_name'],
                $val['storage_id']
            );

            MessageService::sendOutSms(
                $val['materiel_name'],
                $val['type_name'],
                $val['in_storage_num'],
                $val['storage_name'],
                $num,
                $data,
                $val['storage_id'],
                0
            );
        }
    }

    public static function inventoryDetail($data)
    {
        $info = StorageManageModel::query()
            ->select(
                'b.materiel_name',
                'b.type_name',
                'c.class_name as secClassName',
                'd.class_name as firClassName',
                'b.materiel_no',
                'b.number_prefix',
                'e.storage_name',
                'f.shelf_name',
                'g.location_name',
                'b.is_product_materiel',
                'b.materiel_img',
                'b.spec_img',
                'b.materiel_unit',
                'b.selling_price',
                'b.length',
                'b.width',
                'b.weight',
                'b.width',
                'height',
                'b.cost',
                'executive_standard',
                'texture',
                'a.type_id',
                'a.id as storage_manage_id',
                'e.storage_address',
                'b.bar_code',
                'b.inventory_code'
            )->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->leftJoin('storage_shelf as f', 'f.id', '=', 'a.shelf_id')
            ->leftJoin('storage_shelf_location as g', 'g.id', '=', 'a.location_id')
            ->where([
                'a.id' => $data['storage_manage_id'],
                'a.delete_flag' => 0,
                'b.delete_flag' => 0,
            ])->first();

        if (!empty($info)) {
            // 生成PNG格式的条形码并保存到服务器
            if (!empty($info['bar_code'])) {
                $DNS1D = new DNS1D();
                $resl = $DNS1D->getBarcodePNG($info['bar_code'], 'C128A');
                $info['bar_code_img'] = $resl ?? "";
            }
            $info['product_content'] = [];
            if ($info['is_product_materiel'] == 1) {
                $info['product_content'] = MaterielProductContentModel::query()
                    ->select(
                        'a.price',
                        'a.num',
                        'b.materiel_name'
                    )->from('materiel_product_content as a')
                    ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                    ->where([
                        'product_id' => $info['type_id'],
                        'a.delete_flag' => 0
                    ])->get();
            }
            $info['batch_list'] = StorageBatchModel::query()
                ->select('batch_no')
                ->where([
                    'delete_flag' => 0,
                    'storage_manage_id' => $info['storage_manage_id']
                ])->pluck('batch_no') ?? [];
            $info['serial_number_list'] = SerialNumberModel::query()
                ->where([
                    'delete_flag' => 0,
                    'storage_manage_id' => $info['storage_manage_id'],
                    'goods_id' => $info['type_id']
                ])->pluck('serial_no') ?? [];
            $info['animal_info'] = MaterielAnimalInfoModel::query()
                ->where([
                    'delete_flag' => 0,
                    'materiel_type_id' => $info['type_id']
                ])->first();

            $inStorageLogList = LogInStorageModel::query()
                ->select(
                    'b.materiel_name',
                    'b.type_name',
                    'a.created_at',
                    'all_id_type',
                    'operate_num',
                    'nickname'
                )->from('log_instorage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                ->leftJoin('admin as c', 'c.id', '=', 'a.user_id')
                ->where([
                    'a.delete_flag' => 0,
                    'materiel_type_id' => $info['type_id'],
                    'curr_storage_manage_id' => $info['storage_manage_id']
                ])->get();
            if (!empty($inStorageLogList->toArray())) {
                foreach ($inStorageLogList as &$val) {
                    $operateType = '快速入库';
                    switch ($val['all_id_type']) {
                        case 1:
                            $operateType = '报溢入库';
                            break;
                        case 2:
                            $operateType = '退货入库';
                            break;
                        case 3:
                            $operateType = '采购入库';
                            break;
                        case 4:
                            $operateType = '生产还库';
                            break;
                        case 6:
                            $operateType = '组件返仓';
                            break;
                        case 7:
                            $operateType = '导入入库';
                            break;
                        case 8:
                            $operateType = '撤销还库';
                            break;
                        case 9:
                            $operateType = '退换货入库';
                            break;
                        default:
                            $operateType = '快速入库';
                            break;
                    }
                    $val['operate_type'] = $operateType;
                    $val['in_out_type'] = 1;
                }
            }
            $outStorageLogList = LogOutStorageModel::query()
                ->select(
                    'b.materiel_name',
                    'b.type_name',
                    'a.created_at',
                    'all_id_type',
                    'operate_num',
                    'nickname'
                )->from('log_outstorage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                ->leftJoin('admin as c', 'c.id', '=', 'a.user_id')
                ->where([
                    'a.delete_flag' => 0,
                    'materiel_type_id' => $info['type_id'],
                    'curr_storage_manage_id' => $info['storage_manage_id']
                ])->get();

            if (!empty($outStorageLogList->toArray())) {
                foreach ($outStorageLogList as &$val) {
                    $operateType = '快速出库';
                    switch ($val['all_id_type']) {
                        case 1:
                            $operateType = '报损出库';
                            break;
                        case 2:
                            $operateType = '销售出库';
                            break;
                        case 3:
                            $operateType = '生产出库';
                            break;
                        case 4:
                            $operateType = '导入出库';
                            break;
                        case 5:
                            $operateType = '撤销出库';
                            break;
                        case 6:
                            $operateType = '换货出库';
                            break;
                        case 7:
                            $operateType = '生产损耗出库';
                            break;
                        default:
                            $operateType = '快速出库';
                            break;
                    }
                    $val['in_out_type'] = 2;
                    $val['operate_type'] = $operateType;
                }
            }

            $list = array_merge($inStorageLogList->toArray(), $outStorageLogList->toArray());
            if (!empty($list)) {
                $timeKey = array_column($list, 'created_at');
                array_multisort($timeKey, SORT_DESC, $list);
            }
            $info['in_out_list'] = $list ?? '';
            return $info;
        }
        return [];
    }

    public static function getSerialNumberInfo($data)
    {
        $info = SerialNumberModel::query()
            ->select(
                'a.serial_no',
                'b.materiel_name',
                'b.type_name',
                'c.class_name as secClassName',
                'd.class_name as firClassName',
                'b.materiel_no',
                'b.number_prefix',
                'e.storage_name',
                'f.shelf_name',
                'g.location_name',
                'b.is_product_materiel',
                'b.materiel_img',
                'b.spec_img',
                'b.materiel_unit',
                'b.selling_price',
                'b.length',
                'b.width',
                'b.weight',
                'b.width',
                'height',
                'b.cost',
                'executive_standard',
                'texture',
                'a.goods_id as type_id',
                'h.id as storage_manage_id',
                'bar_code'
            )->from('serial_number as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.goods_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
            ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
            ->leftJoin('storage_manage as h', 'h.id', '=', 'a.storage_manage_id')
            ->leftJoin('storage as e', 'e.id', '=', 'h.storage_id')
            ->leftJoin('storage_shelf as f', 'f.id', '=', 'h.shelf_id')
            ->leftJoin('storage_shelf_location as g', 'g.id', '=', 'h.location_id')
            ->where([
                'a.delete_flag' => 0,
                'a.id' => $data['serialId'],
                'b.delete_flag' => 0,
                'h.delete_flag' => 0,
            ])->first();

        if (!empty($info)) {
            // 生成PNG格式的条形码并保存到服务器
            if (!empty($info['bar_code'])) {
                $DNS1D = new DNS1D();
                $resl = $DNS1D->getBarcodePNG($info['bar_code'], 'C128A');
                $info['bar_code_img'] = $resl ?? "";
            }
            $info['product_content'] = '';
            if ($info['is_product_materiel'] == 1) {
                $info['product_content'] = MaterielProductContentModel::query()
                    ->select(
                        'a.price',
                        'a.num',
                        'b.materiel_name'
                    )->from('materiel_product_content as a')
                    ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
                    ->where([
                        'product_id' => $info['type_id'],
                        'a.delete_flag' => 0
                    ])->get();
            }

            $info['animal_info'] = MaterielAnimalInfoModel::query()
                ->where([
                    'delete_flag' => 0,
                    'materiel_type_id' => $info['type_id']
                ])->first() ?? '';

            $inStorageLogList = LogInStorageModel::query()
                ->select(
                    'b.materiel_name',
                    'b.type_name',
                    'a.created_at',
                    'all_id_type',
                    'operate_num',
                    'nickname'
                )->from('log_instorage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                ->leftJoin('admin as c', 'c.id', '=', 'a.user_id')
                ->where([
                    'a.delete_flag' => 0,
                    'materiel_type_id' => $info['type_id'],
                    'curr_storage_manage_id' => $info['storage_manage_id']
                ])->get();
            if (!empty($inStorageLogList->toArray())) {
                foreach ($inStorageLogList as &$val) {
                    $operateType = '快速入库';
                    switch ($val['all_id_type']) {
                        case 1:
                            $operateType = '报溢入库';
                            break;
                        case 2:
                            $operateType = '退货入库';
                            break;
                        case 3:
                            $operateType = '采购入库';
                            break;
                        case 4:
                            $operateType = '生产还库';
                            break;
                        case 6:
                            $operateType = '组件返仓';
                            break;
                        case 7:
                            $operateType = '导入入库';
                            break;
                        case 8:
                            $operateType = '撤销还库';
                            break;
                        case 9:
                            $operateType = '退换货入库';
                            break;
                        default:
                            $operateType = '快速入库';
                            break;
                    }
                    $val['in_out_type'] = 1;
                    $val['operate_type'] = $operateType;
                }
            }
            $outStorageLogList = LogOutStorageModel::query()
                ->select(
                    'b.materiel_name',
                    'b.type_name',
                    'a.created_at',
                    'all_id_type',
                    'operate_num',
                    'nickname'
                )->from('log_outstorage as a')
                ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
                ->leftJoin('admin as c', 'c.id', '=', 'a.user_id')
                ->where([
                    'a.delete_flag' => 0,
                    'materiel_type_id' => $info['type_id'],
                    'curr_storage_manage_id' => $info['storage_manage_id']
                ])->get();

            if (!empty($outStorageLogList->toArray())) {
                foreach ($outStorageLogList as &$val) {
                    $operateType = '快速出库';
                    switch ($val['all_id_type']) {
                        case 1:
                            $operateType = '报损出库';
                            break;
                        case 2:
                            $operateType = '销售出库';
                            break;
                        case 3:
                            $operateType = '生产出库';
                            break;
                        case 4:
                            $operateType = '导入出库';
                            break;
                        case 5:
                            $operateType = '撤销出库';
                            break;
                        case 6:
                            $operateType = '换货出库';
                            break;
                        case 7:
                            $operateType = '生产损耗出库';
                            break;
                        default:
                            $operateType = '快速出库';
                            break;
                    }
                    $val['in_out_type'] = 2;
                    $val['operate_type'] = $operateType;
                }
            }

            $list = array_merge($inStorageLogList->toArray(), $outStorageLogList->toArray());
            if (!empty($list)) {
                $timeKey = array_column($list, 'created_at');
                array_multisort($timeKey, SORT_DESC, $list);
            }
            $info['in_out_list'] = $list ?? '';
            return $info;
        }
        return [];
    }

    /**
     *库位详情(H5)
     * Author: zlf
     * Created at 2024/5/23 11:14
     * @param $data
     * @return array|\Illuminate\Database\Eloquent\Builder|Model|object
     */
    public static function getStorageLocationInfo($data)
    {
        $storageInfo = StorageModel::query()
            ->select(
                'a.id as storage_id',
                'storage_name',
                'storage_address',
                'd.nickname'
            )->from('storage as a')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id');
        if (!empty($data['storage_id'])) {
            $storageInfo->where('a.id', $data['storage_id']);
        } elseif (!empty($data['shelf_id'])) {
            $storageInfo->addSelect(
                'b.id as shelf_id',
                'shelf_name',
            )->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
                ->where('b.id', $data['shelf_id']);
        } elseif (!empty($data['location_id'])) {
            $storageInfo->addSelect(
                'b.id as shelf_id',
                'shelf_name',
                'c.id as location_id',
                'location_name',
            )->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
                ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
                ->where('c.id', $data['location_id']);
        }
        $storageInfo = $storageInfo->where(
            function ($query) use ($data) {
                if (!empty($data['shelf_id'])) {
                    $query->where('b.status', 1);
                }
                if (!empty($data['location_id'])) {
                    $query->where('b.status', 1);
                    $query->where('c.status', 1);
                }
            })->where('a.delete_flag', 0)->first();

        if (empty($storageInfo)) return "";
        $storageList = StorageModel::query()
            ->select(
                'location_name',
                'shelf_name',
                'storage_name',
                'c.id as location_id',
                'b.id as shelf_id',
                'a.id as storage_id',
                'a.storage_address',
            )->from('storage as a')
            ->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.id')
            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
            ->where(function ($query) use ($data) {
                if (!empty($data['storage_id'])) {
                    $query->where('a.id', $data['storage_id']);
                } elseif (!empty($data['shelf_id'])) {
                    $query->where('b.id', $data['shelf_id']);
                } elseif (!empty($data['location_id'])) {
                    $query->where('c.id', $data['location_id']);
                }
            })->where([
                'a.delete_flag' => 0,
                'b.status' => 1,
                'c.status' => 1
            ])->get();
        $storageInfo['shelf_location_list'] = [];
        if (empty($storageList->toArray())) return $storageInfo;
        $storageList = $storageList->toArray();
        $storageManageList = StorageManageModel::query()
            ->select(
                "b.materiel_name",
                "b.materiel_no",
                "b.type_name",
                "in_storage_num",
                "storage_id",
                "shelf_id",
                "location_id"
            )->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->where([
                'a.delete_flag' => 0
            ])->where(function ($query) use ($data) {
                if (!empty($data['storage_id'])) {
                    $query->where('a.storage_id', $data['storage_id']);
                } elseif (!empty($data['shelf_id'])) {
                    $query->where('a.shelf_id', $data['shelf_id']);
                } elseif (!empty($data['location_id'])) {
                    $query->where('a.location_id', $data['location_id']);
                }
            })->get();

        $storageManageList = !empty($storageManageList->toArray()) ? $storageManageList->toArray() : "";
        $d = array();
        foreach ($storageList as $fKey => &$fVal) {
            $fVal['goods_list'] = array();
            if (!empty($storageManageList)) {
                foreach ($storageManageList as $sVal) {
                    if ($fVal['location_id'] == $sVal['location_id']) {
                        $fVal['goods_list'][] = $sVal;
                    }
                }
            }
            if (!empty($fVal['goods_list'])) {
                $d[] = $fVal;
            }
        }

        $storageInfo['shelf_location_list'] = $d;
        $standardnumInfo = StorageShelfLocationModel::query()
            ->where([
                'status' => 1,
                ['standard_num', '>', 0]
            ]);
        $manageInfo = StorageManageModel::query()
            ->where([
                'delete_flag' => 0,
                ['in_storage_num', '>', 0]
            ]);
        if (!empty($data['storage_id'])) {
            $standardnumInfo->where('storage_id', $data['storage_id']);
            $manageInfo->where('storage_id', $data['storage_id']);
        } elseif (!empty($data['shelf_id'])) {
            $standardnumInfo->where('shelf_id', $data['shelf_id']);
            $manageInfo->where('shelf_id', $data['shelf_id']);
        } elseif (!empty($data['location_id'])) {

            $standardnumInfo->where('id', $data['location_id']);
            $manageInfo->where('location_id', $data['location_id']);
        }
        $storageInfo['standard_num'] = $standardnumInfo->sum('standard_num') ?? 0;
        $storageInfo['total_num'] = $manageInfo->sum('in_storage_num') ?? 0;
        return $storageInfo;
    }
}
